use crate::tec::TranslationalEquivalence;
use crate::sia::find_mtps;
use std::collections::HashSet;
pub fn exact_match_pattern(
dataset: &[(u32, u32)],
pattern: &[(u32, u32)],
restrict_dpitch_zero: bool,
) -> HashSet<(i32, i32)> {
debug_assert!(
dataset.windows(2).all(|w| w[0] <= w[1]),
"dataset must be lexicographically sorted"
);
debug_assert!(
pattern.windows(2).all(|w| w[0] <= w[1]),
"pattern must be lexicographically sorted"
);
let m = pattern.len();
let n = dataset.len();
if m < 2 || n < m {
return HashSet::new();
}
let mut q = vec![0usize; m];
let p0 = pattern[0];
let mut translators = HashSet::new();
for j in 0..=(n - m) {
let (tj, pj) = dataset[j];
if restrict_dpitch_zero && pj != p0.1 {
continue;
}
let f = (tj as i32 - p0.0 as i32, pj as i32 - p0.1 as i32);
if f == (0, 0) || (restrict_dpitch_zero && f.1 != 0) {
continue;
}
q[0] = q[0].max(j);
let mut matched = true;
for idx in 1..m {
let target = (
(pattern[idx].0 as i32 + f.0) as u32,
(pattern[idx].1 as i32 + f.1) as u32,
);
let mut ptr = q[idx].max(q[idx - 1]); while ptr < n && dataset[ptr] < target {
ptr += 1;
}
q[idx] = ptr;
if ptr >= n || dataset[ptr] != target {
matched = false;
break;
}
}
if matched {
translators.insert(f);
}
}
translators
}
pub fn build_tecs_from_mtps(
dataset: &Vec<(u32, u32)>,
restrict_dpitch_zero: bool,
) -> Vec<TranslationalEquivalence> {
let mtps = find_mtps(dataset, restrict_dpitch_zero);
let mut tecs = Vec::new();
for (v, pattern) in mtps {
if v == (0, 0) || pattern.len() < 2 {
continue;
}
let translators = exact_match_pattern(dataset, &pattern, restrict_dpitch_zero);
if !translators.is_empty() {
tecs.push(TranslationalEquivalence::new(pattern, translators, None));
}
}
tecs
}