crate::ix!();
pub trait CompareCapstone {
fn compare_capstone(&self, other: &GrowerTreeConfiguration) -> CompareOutcome;
}
impl CompareCapstone for GrowerTreeConfiguration {
fn compare_capstone(&self, other: &GrowerTreeConfiguration) -> CompareOutcome {
match (self.capstone(), other.capstone()) {
(None, None) => CompareOutcome::Exact,
(None, Some(cfg)) => {
if *cfg.mode() == CapstoneMode::Off {
CompareOutcome::Exact
} else {
CompareOutcome::Incompatible
}
},
(Some(cfg), None) => {
if *cfg.mode() == CapstoneMode::Off {
CompareOutcome::Exact
} else {
CompareOutcome::Incompatible
}
},
(Some(a), Some(b)) => {
if a.mode() != b.mode() {
return CompareOutcome::Incompatible;
}
let diff = (a.probability() - b.probability()).abs();
if diff < 0.01 {
CompareOutcome::Exact
} else if diff <= 0.2 {
CompareOutcome::Partial(1.0 - diff)
} else {
CompareOutcome::Incompatible
}
}
}
}
}
#[cfg(test)]
mod compare_capstone_tests {
use super::*;
#[traced_test]
fn none_none_exact() {
let a = GrowerTreeConfiguration::default();
let b = GrowerTreeConfiguration::default();
assert_eq!(a.compare_capstone(&b), CompareOutcome::Exact);
}
#[traced_test]
fn same_mode_prob_exact() {
let cap = CapstoneGenerationConfigurationBuilder::default()
.mode(CapstoneMode::Probabilistic)
.probability(0.3)
.build()
.unwrap();
let a = GrowerTreeConfiguration::default()
.to_builder().capstone(Some(cap.clone())).build().unwrap();
let b = a.clone();
assert_eq!(a.compare_capstone(&b), CompareOutcome::Exact);
}
#[traced_test]
fn same_mode_different_prob_partial() {
let cap_a = CapstoneGenerationConfigurationBuilder::default()
.mode(CapstoneMode::Probabilistic)
.probability(0.2)
.build()
.unwrap();
let cap_b = CapstoneGenerationConfigurationBuilder::default()
.mode(CapstoneMode::Probabilistic)
.probability(0.4)
.build()
.unwrap();
let a = GrowerTreeConfiguration::default()
.to_builder().capstone(Some(cap_a)).build().unwrap();
let b = a.to_builder().capstone(Some(cap_b)).build().unwrap();
let out = a.compare_capstone(&b);
match out {
CompareOutcome::Partial(_) => {},
other => panic!("expected partial, got {:?}", other),
}
}
#[traced_test]
fn off_vs_single_incompatible() {
let off = CapstoneGenerationConfigurationBuilder::default()
.mode(CapstoneMode::Off)
.probability(0.0)
.build()
.unwrap();
let single = CapstoneGenerationConfigurationBuilder::default()
.mode(CapstoneMode::Single)
.probability(0.0)
.build()
.unwrap();
let a = GrowerTreeConfiguration::default()
.to_builder().capstone(Some(off)).build().unwrap();
let b = a.to_builder().capstone(Some(single)).build().unwrap();
let outcome = a.compare_capstone(&b);
assert_eq!(outcome, CompareOutcome::Incompatible, "Off vs Single => Incompatible");
}
#[traced_test]
fn one_none_one_probabilistic_incompatible() {
let prob = CapstoneGenerationConfigurationBuilder::default()
.mode(CapstoneMode::Probabilistic)
.probability(0.6)
.build()
.unwrap();
let a = GrowerTreeConfiguration::default();
let b = a.to_builder().capstone(Some(prob)).build().unwrap();
assert_eq!(a.compare_capstone(&b), CompareOutcome::Incompatible);
}
}