// Copyright © 2024 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See .
use 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::{Seed, 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 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::);
}