use std::cmp::Ordering;
pub fn multiset_intersection<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
let mut result = Vec::new();
let mut i1 = 0;
let mut i2 = 0;
while i1 < first1.len() && i2 < first2.len() {
match pred(&first1[i1], &first2[i2]) {
Ordering::Less => i1 += 1, Ordering::Greater => i2 += 1, Ordering::Equal => {
result.push(first1[i1].clone());
i1 += 1;
}
}
}
result
}
pub fn multiset_1small_intersection<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
let mut result = Vec::new();
let mut i1 = 0;
let mut i2 = 0;
while i1 < first1.len() && i2 < first2.len() {
let range = equal_range(&first2[i2..], &first1[i1], &pred);
if range.start == range.end {
i1 += 1;
} else {
let range_start = &first2[i2 + range.start];
while i1 < first1.len() && pred(&first1[i1], range_start) == Ordering::Equal {
result.push(first1[i1].clone());
i1 += 1;
}
}
i2 += range.end;
}
result
}
pub fn multiset_fast_intersection<T, F>(
first1: &[T],
first2: &[T],
pred: F,
threshold: usize,
) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
if first1.len() * threshold < first2.len() {
multiset_1small_intersection(first1, first2, pred)
} else {
multiset_intersection(first1, first2, pred)
}
}
pub fn multiset_intersection2<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
let mut result = Vec::new();
let mut i1 = 0;
let mut i2 = 0;
while i1 < first1.len() && i2 < first2.len() {
match pred(&first1[i1], &first2[i2]) {
Ordering::Less => i1 += 1, Ordering::Greater => i2 += 1, Ordering::Equal => {
result.push(first2[i2].clone());
i2 += 1;
}
}
}
result
}
pub fn multiset_1small_intersection2<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
let mut result = Vec::new();
let mut i1 = 0;
let mut i2 = 0;
while i1 < first1.len() && i2 < first2.len() {
let range = equal_range(&first2[i2..], &first1[i1], &pred);
if range.start != range.end {
for idx in (i2 + range.start)..(i2 + range.end) {
result.push(first2[idx].clone());
}
}
i2 += range.end;
i1 += 1;
}
result
}
pub fn multiset_fast_intersection2<T, F>(
first1: &[T],
first2: &[T],
pred: F,
threshold: usize,
) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
if first1.len() * threshold < first2.len() {
multiset_1small_intersection2(first1, first2, pred)
} else {
multiset_intersection2(first1, first2, pred)
}
}
pub fn set_unique<T, F>(data: &mut [T], pred: F) -> usize
where
F: Fn(&T, &T) -> bool,
{
if data.len() <= 1 {
return data.len();
}
let mut write_pos = 0;
let mut read_pos = 0;
while read_pos < data.len() {
if write_pos == 0 || !pred(&data[write_pos - 1], &data[read_pos]) {
if write_pos != read_pos {
data.swap(write_pos, read_pos);
}
write_pos += 1;
}
read_pos += 1;
}
write_pos
}
pub fn set_unique_default<T: PartialEq>(data: &mut [T]) -> usize {
set_unique(data, |a, b| a == b)
}
pub fn multiset_union<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
let mut result = Vec::with_capacity(first1.len() + first2.len());
let mut i1 = 0;
let mut i2 = 0;
while i1 < first1.len() && i2 < first2.len() {
match pred(&first1[i1], &first2[i2]) {
Ordering::Less => {
result.push(first1[i1].clone());
i1 += 1;
}
Ordering::Greater => {
result.push(first2[i2].clone());
i2 += 1;
}
Ordering::Equal => {
result.push(first1[i1].clone());
result.push(first2[i2].clone());
i1 += 1;
i2 += 1;
}
}
}
while i1 < first1.len() {
result.push(first1[i1].clone());
i1 += 1;
}
while i2 < first2.len() {
result.push(first2[i2].clone());
i2 += 1;
}
result
}
pub fn multiset_difference<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone,
F: Fn(&T, &T) -> Ordering,
{
let mut result = Vec::new();
let mut i1 = 0;
let mut i2 = 0;
while i1 < first1.len() && i2 < first2.len() {
match pred(&first1[i1], &first2[i2]) {
Ordering::Less => {
result.push(first1[i1].clone());
i1 += 1;
}
Ordering::Greater => {
i2 += 1;
}
Ordering::Equal => {
i1 += 1;
i2 += 1;
}
}
}
while i1 < first1.len() {
result.push(first1[i1].clone());
i1 += 1;
}
result
}
pub fn set_intersection<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone + PartialEq,
F: Fn(&T, &T) -> Ordering,
{
let mut result = multiset_intersection(first1, first2, pred);
let new_len = set_unique_default(&mut result);
result.truncate(new_len);
result
}
pub fn set_union<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone + PartialEq,
F: Fn(&T, &T) -> Ordering,
{
let mut result = multiset_union(first1, first2, pred);
let new_len = set_unique_default(&mut result);
result.truncate(new_len);
result
}
pub fn set_difference<T, F>(first1: &[T], first2: &[T], pred: F) -> Vec<T>
where
T: Clone + PartialEq,
F: Fn(&T, &T) -> Ordering,
{
let mut result = multiset_difference(first1, first2, pred);
let new_len = set_unique_default(&mut result);
result.truncate(new_len);
result
}
fn equal_range<T, F>(data: &[T], value: &T, pred: &F) -> std::ops::Range<usize>
where
F: Fn(&T, &T) -> Ordering,
{
let lower = lower_bound(data, value, pred);
let upper = upper_bound(data, value, pred);
lower..upper
}
fn lower_bound<T, F>(data: &[T], value: &T, pred: &F) -> usize
where
F: Fn(&T, &T) -> Ordering,
{
let mut left = 0;
let mut right = data.len();
while left < right {
let mid = left + (right - left) / 2;
if pred(&data[mid], value) == Ordering::Less {
left = mid + 1;
} else {
right = mid;
}
}
left
}
fn upper_bound<T, F>(data: &[T], value: &T, pred: &F) -> usize
where
F: Fn(&T, &T) -> Ordering,
{
let mut left = 0;
let mut right = data.len();
while left < right {
let mid = left + (right - left) / 2;
if pred(value, &data[mid]) == Ordering::Less {
right = mid;
} else {
left = mid + 1;
}
}
left
}
#[cfg(test)]
mod tests {
use super::*;
fn cmp_i32(a: &i32, b: &i32) -> Ordering {
a.cmp(b)
}
#[test]
fn test_multiset_intersection_basic() {
let a = vec![1, 2, 2, 3, 4, 5];
let b = vec![2, 2, 3, 6, 7];
let result = multiset_intersection(&a, &b, cmp_i32);
assert_eq!(result, vec![2, 2, 3]);
}
#[test]
fn test_multiset_intersection_empty() {
let a: Vec<i32> = vec![];
let b = vec![1, 2, 3];
let result = multiset_intersection(&a, &b, cmp_i32);
assert_eq!(result, Vec::<i32>::new());
let a = vec![1, 2, 3];
let b: Vec<i32> = vec![];
let result = multiset_intersection(&a, &b, cmp_i32);
assert_eq!(result, Vec::<i32>::new());
}
#[test]
fn test_multiset_intersection_no_overlap() {
let a = vec![1, 2, 3];
let b = vec![4, 5, 6];
let result = multiset_intersection(&a, &b, cmp_i32);
assert_eq!(result, Vec::<i32>::new());
}
#[test]
fn test_multiset_intersection_duplicates() {
let a = vec![1, 1, 1, 2, 2, 3];
let b = vec![1, 1, 2, 2, 2, 3, 3];
let result = multiset_intersection(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 1, 1, 2, 2, 3]);
}
#[test]
fn test_multiset_intersection_complete_overlap() {
let a = vec![1, 2, 3, 4, 5];
let b = vec![1, 2, 3, 4, 5];
let result = multiset_intersection(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_multiset_1small_intersection() {
let a = vec![2, 3, 5]; let b = vec![1, 2, 2, 3, 3, 3, 4, 5, 5, 6]; let result = multiset_1small_intersection(&a, &b, cmp_i32);
assert_eq!(result, vec![2, 3, 5]);
}
#[test]
fn test_multiset_1small_intersection_many_duplicates() {
let a = vec![2, 2, 2, 3];
let b = vec![1, 2, 2, 2, 2, 3, 3, 4];
let result = multiset_1small_intersection(&a, &b, cmp_i32);
assert_eq!(result, vec![2, 2, 2, 3]);
}
#[test]
fn test_multiset_fast_intersection_small_first() {
let a = vec![1, 2, 3];
let b: Vec<i32> = (1..=100).collect();
let result = multiset_fast_intersection(&a, &b, cmp_i32, 32);
assert_eq!(result, vec![1, 2, 3]);
}
#[test]
fn test_multiset_fast_intersection_large_first() {
let a: Vec<i32> = (1..=100).collect();
let b = vec![1, 2, 3];
let result = multiset_fast_intersection(&a, &b, cmp_i32, 32);
assert_eq!(result, vec![1, 2, 3]);
}
#[test]
fn test_multiset_intersection2() {
let a = vec![1, 2, 2, 3];
let b = vec![2, 2, 2, 3, 4];
let result = multiset_intersection2(&a, &b, cmp_i32);
assert_eq!(result, vec![2, 2, 2, 3]);
}
#[test]
fn test_multiset_intersection2_asymmetric() {
let a = vec![1, 1, 1, 2];
let b = vec![1, 2, 2];
let result = multiset_intersection2(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 2]);
}
#[test]
fn test_multiset_1small_intersection2() {
let a = vec![2, 3];
let b = vec![1, 2, 2, 2, 3, 3, 4];
let result = multiset_1small_intersection2(&a, &b, cmp_i32);
assert_eq!(result, vec![2, 2, 2, 3, 3]);
}
#[test]
fn test_multiset_fast_intersection2() {
let a = vec![1, 2];
let b: Vec<i32> = (1..=100).collect();
let result = multiset_fast_intersection2(&a, &b, cmp_i32, 32);
assert_eq!(result, vec![1, 2]);
}
#[test]
fn test_set_unique() {
let mut data = vec![1, 1, 2, 2, 2, 3, 4, 4, 5];
let new_len = set_unique(&mut data, |a, b| a == b);
data.truncate(new_len);
assert_eq!(data, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_set_unique_single() {
let mut data = vec![42];
let new_len = set_unique_default(&mut data);
assert_eq!(new_len, 1);
assert_eq!(data, vec![42]);
}
#[test]
fn test_set_unique_empty() {
let mut data: Vec<i32> = vec![];
let new_len = set_unique_default(&mut data);
assert_eq!(new_len, 0);
}
#[test]
fn test_set_unique_no_duplicates() {
let mut data = vec![1, 2, 3, 4, 5];
let new_len = set_unique_default(&mut data);
assert_eq!(new_len, 5);
assert_eq!(data, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_set_unique_all_same() {
let mut data = vec![7, 7, 7, 7, 7];
let new_len = set_unique_default(&mut data);
data.truncate(new_len);
assert_eq!(data, vec![7]);
}
#[test]
fn test_multiset_union() {
let a = vec![1, 2, 3, 4];
let b = vec![3, 4, 5, 6];
let result = multiset_union(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3, 3, 4, 4, 5, 6]);
}
#[test]
fn test_multiset_union_no_overlap() {
let a = vec![1, 2, 3];
let b = vec![4, 5, 6];
let result = multiset_union(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_multiset_union_with_duplicates() {
let a = vec![1, 1, 2, 3];
let b = vec![2, 2, 3, 4];
let result = multiset_union(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 1, 2, 2, 2, 3, 3, 4]);
}
#[test]
fn test_multiset_union_empty() {
let a: Vec<i32> = vec![];
let b = vec![1, 2, 3];
let result = multiset_union(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3]);
let a = vec![1, 2, 3];
let b: Vec<i32> = vec![];
let result = multiset_union(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3]);
}
#[test]
fn test_multiset_difference() {
let a = vec![1, 2, 2, 3, 4];
let b = vec![2, 3, 3, 5];
let result = multiset_difference(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 4]);
}
#[test]
fn test_multiset_difference_no_overlap() {
let a = vec![1, 2, 3];
let b = vec![4, 5, 6];
let result = multiset_difference(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3]);
}
#[test]
fn test_multiset_difference_complete_overlap() {
let a = vec![1, 2, 3];
let b = vec![1, 2, 3];
let result = multiset_difference(&a, &b, cmp_i32);
assert_eq!(result, Vec::<i32>::new());
}
#[test]
fn test_multiset_difference_empty() {
let a: Vec<i32> = vec![];
let b = vec![1, 2, 3];
let result = multiset_difference(&a, &b, cmp_i32);
assert_eq!(result, Vec::<i32>::new());
let a = vec![1, 2, 3];
let b: Vec<i32> = vec![];
let result = multiset_difference(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3]);
}
#[test]
fn test_set_intersection_unique() {
let a = vec![1, 2, 2, 3, 4];
let b = vec![2, 2, 3, 5];
let result = set_intersection(&a, &b, cmp_i32);
assert_eq!(result, vec![2, 3]); }
#[test]
fn test_set_union_unique() {
let a = vec![1, 2, 2, 3];
let b = vec![2, 3, 4, 4];
let result = set_union(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 3, 4]); }
#[test]
fn test_set_difference_unique() {
let a = vec![1, 2, 2, 3, 4, 4];
let b = vec![2, 3];
let result = set_difference(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 2, 4]); }
#[test]
fn test_large_datasets_intersection() {
let a: Vec<i32> = (0..1_000_000).filter(|x| x % 2 == 0).collect();
let b: Vec<i32> = (0..1_000_000).filter(|x| x % 3 == 0).collect();
let result = multiset_fast_intersection(&a, &b, cmp_i32, 32);
let expected: Vec<i32> = (0..1_000_000).filter(|x| x % 6 == 0).collect();
assert_eq!(result, expected);
}
#[test]
fn test_large_datasets_union() {
let a: Vec<i32> = (0..10_000).filter(|x| x % 2 == 0).collect();
let b: Vec<i32> = (0..10_000).filter(|x| x % 3 == 0).collect();
let result = multiset_union(&a, &b, cmp_i32);
for i in 1..result.len() {
assert!(result[i - 1] <= result[i]);
}
let expected_size = a.len() + b.len();
assert_eq!(result.len(), expected_size);
}
#[test]
fn test_large_datasets_difference() {
let a: Vec<i32> = (0..10_000).collect();
let b: Vec<i32> = (5_000..15_000).collect();
let result = multiset_difference(&a, &b, cmp_i32);
let expected: Vec<i32> = (0..5_000).collect();
assert_eq!(result, expected);
}
#[test]
fn test_performance_comparison() {
let small: Vec<i32> = (0..100).collect();
let large: Vec<i32> = (0..10_000).collect();
let result1 = multiset_1small_intersection(&small, &large, cmp_i32);
let result2 = multiset_intersection(&small, &large, cmp_i32);
let result3 = multiset_fast_intersection(&small, &large, cmp_i32, 32);
assert_eq!(result1, result2);
assert_eq!(result1, result3);
}
#[test]
fn test_adaptive_selection_boundary() {
let a: Vec<i32> = (0..10).collect();
let b: Vec<i32> = (0..320).collect();
let result = multiset_fast_intersection(&a, &b, cmp_i32, 32);
let expected: Vec<i32> = (0..10).collect();
assert_eq!(result, expected);
}
#[test]
fn test_equal_range() {
let data = vec![1, 2, 2, 2, 3, 3, 4, 5];
let range = equal_range(&data, &2, &cmp_i32);
assert_eq!(range, 1..4);
let range = equal_range(&data, &3, &cmp_i32);
assert_eq!(range, 4..6);
let range = equal_range(&data, &10, &cmp_i32);
assert_eq!(range, 8..8); }
#[test]
fn test_lower_bound() {
let data = vec![1, 2, 2, 2, 3, 3, 4, 5];
assert_eq!(lower_bound(&data, &2, &cmp_i32), 1);
assert_eq!(lower_bound(&data, &3, &cmp_i32), 4);
assert_eq!(lower_bound(&data, &0, &cmp_i32), 0);
assert_eq!(lower_bound(&data, &10, &cmp_i32), 8);
}
#[test]
fn test_upper_bound() {
let data = vec![1, 2, 2, 2, 3, 3, 4, 5];
assert_eq!(upper_bound(&data, &2, &cmp_i32), 4);
assert_eq!(upper_bound(&data, &3, &cmp_i32), 6);
assert_eq!(upper_bound(&data, &0, &cmp_i32), 0);
assert_eq!(upper_bound(&data, &10, &cmp_i32), 8);
}
#[test]
fn test_single_element_sequences() {
let a = vec![5];
let b = vec![5];
assert_eq!(multiset_intersection(&a, &b, cmp_i32), vec![5]);
assert_eq!(multiset_union(&a, &b, cmp_i32), vec![5, 5]);
assert_eq!(multiset_difference(&a, &b, cmp_i32), Vec::<i32>::new());
let a = vec![3];
let b = vec![5];
assert_eq!(multiset_intersection(&a, &b, cmp_i32), Vec::<i32>::new());
assert_eq!(multiset_union(&a, &b, cmp_i32), vec![3, 5]);
assert_eq!(multiset_difference(&a, &b, cmp_i32), vec![3]);
}
#[test]
fn test_all_duplicates() {
let a = vec![1, 1, 1, 1];
let b = vec![1, 1, 1];
let result = multiset_intersection(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 1, 1, 1]);
let result = multiset_intersection2(&a, &b, cmp_i32);
assert_eq!(result, vec![1, 1, 1]);
}
}