use super::CliffSearch;
#[derive(Debug, Clone)]
pub struct BinaryMinSearcher {
min_in: core::ops::Range<usize>,
last: Option<usize>,
fidelity: usize,
overloaded: bool,
done: bool,
}
impl BinaryMinSearcher {
pub fn until(start: usize, min_width: usize) -> Self {
Self {
min_in: 0..start,
fidelity: min_width,
last: None,
overloaded: false,
done: false,
}
}
pub fn overloaded(&mut self) {
self.overloaded = true;
}
pub fn estimate(&self) -> core::ops::Range<usize> {
self.min_in.clone()
}
}
impl CliffSearch for BinaryMinSearcher {
fn overloaded(&mut self) {
BinaryMinSearcher::overloaded(self)
}
fn estimate(&self) -> core::ops::Range<usize> {
BinaryMinSearcher::estimate(self)
}
}
impl Iterator for BinaryMinSearcher {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
if let Some(ref mut last) = self.last {
if self.overloaded {
self.min_in.start = *last;
self.overloaded = false;
} else {
self.min_in.end = *last;
}
let next = self.min_in.start + (self.min_in.end - self.min_in.start) / 2;
if self.min_in.end - self.min_in.start > self.fidelity {
*last = next;
Some(next)
} else {
self.done = true;
None
}
} else {
self.last = Some(self.min_in.end);
return self.last;
}
}
}
#[test]
fn search_from_until() {
let mut scale = BinaryMinSearcher::until(1024, 8);
assert_eq!(scale.next(), Some(1024));
assert_eq!(scale.next(), Some(512));
assert_eq!(scale.next(), Some(256));
assert_eq!(scale.next(), Some(128));
assert_eq!(scale.next(), Some(64));
scale.overloaded();
assert_eq!(scale.next(), Some(96));
assert_eq!(scale.next(), Some(80));
scale.overloaded();
assert_eq!(scale.next(), Some(88));
assert_eq!(scale.next(), None);
assert_eq!(scale.estimate(), 80..88);
assert_eq!(scale.next(), None);
scale.overloaded();
assert_eq!(scale.next(), None);
assert_eq!(scale.estimate(), 80..88);
}
#[test]
fn through_trait() {
let mut scale = BinaryMinSearcher::until(1024, 8);
let scale: &mut dyn CliffSearch = &mut scale;
assert_eq!(scale.next(), Some(1024));
assert_eq!(scale.next(), Some(512));
assert_eq!(scale.next(), Some(256));
assert_eq!(scale.next(), Some(128));
assert_eq!(scale.next(), Some(64));
scale.overloaded();
assert_eq!(scale.next(), Some(96));
assert_eq!(scale.next(), Some(80));
scale.overloaded();
assert_eq!(scale.next(), Some(88));
assert_eq!(scale.next(), None);
assert_eq!(scale.estimate(), 80..88);
assert_eq!(scale.next(), None);
scale.overloaded();
assert_eq!(scale.next(), None);
assert_eq!(scale.estimate(), 80..88);
}
#[test]
fn immediate() {
let mut scale = BinaryMinSearcher::until(1024, 8);
assert_eq!(scale.next(), Some(1024));
scale.overloaded();
assert_eq!(scale.next(), None);
assert_eq!(scale.estimate(), 1024..1024);
}