use super::*;
use std::iter;
#[derive(Debug)]
pub struct Iterator {
index: usize,
offset: usize,
factor: usize,
}
impl Iterator {
#[inline]
pub fn new(index: usize) -> Self {
let mut instance = Self {
index: 0,
offset: 0,
factor: 0,
};
instance.seek(index);
instance
}
#[inline]
pub fn index(&self) -> usize {
self.index
}
#[inline]
pub fn offset(&self) -> usize {
self.offset
}
#[inline]
pub fn factor(&self) -> usize {
self.factor
}
#[inline]
pub fn seek(&mut self, index: usize) {
self.index = index;
if is_odd(self.index) {
self.offset = offset(index);
self.factor = two_pow(depth(index) + 1);
} else {
self.offset = index / 2;
self.factor = 2;
}
}
#[inline]
pub fn is_left(&self) -> bool {
is_even(self.offset)
}
#[inline]
pub fn is_right(&self) -> bool {
is_odd(self.offset)
}
#[inline]
pub fn prev(&mut self) -> usize {
if self.offset == 0 {
return self.index;
}
self.offset -= 1;
self.index -= self.factor;
self.index
}
#[inline]
pub fn sibling(&mut self) -> usize {
if self.is_left() {
self.next().unwrap() } else {
self.prev()
}
}
#[inline]
pub fn parent(&mut self) -> usize {
if is_odd(self.offset) {
self.index -= self.factor / 2;
self.offset = (self.offset - 1) / 2;
} else {
self.index += self.factor / 2;
self.offset /= 2;
}
self.factor *= 2;
self.index
}
#[inline]
pub fn left_span(&mut self) -> usize {
self.index = self.index + 1 - self.factor / 2;
self.offset = self.index / 2;
self.factor = 2;
self.index
}
#[inline]
pub fn right_span(&mut self) -> usize {
self.index = self.index + self.factor / 2 - 1;
self.offset = self.index / 2;
self.factor = 2;
self.index
}
#[inline]
pub fn left_child(&mut self) -> usize {
if self.factor == 2 {
return self.index;
}
self.factor /= 2;
self.index -= self.factor / 2;
self.offset *= 2;
self.index
}
#[inline]
pub fn right_child(&mut self) -> usize {
if self.factor == 2 {
return self.index;
}
self.factor /= 2;
self.index += self.factor / 2;
self.offset = 2 * self.offset + 1;
self.index
}
}
impl iter::Iterator for Iterator {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.offset += 1;
self.index += self.factor;
Some(self.index)
}
}
impl Default for Iterator {
#[inline]
fn default() -> Self {
Self::new(0)
}
}
#[inline]
fn two_pow(n: usize) -> usize {
if n < 31 {
1 << n
} else {
((1 << 30) * (1 << (n - 30)))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_two_pow() {
assert_eq!(two_pow(0), 1);
assert_eq!(two_pow(1), 2);
assert_eq!(two_pow(2), 4);
assert_eq!(two_pow(3), 8);
assert_eq!(two_pow(31), 2147483648);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_two_pow_64bit() {
assert_eq!(two_pow(34), 17179869184);
assert_eq!(two_pow(63), 9223372036854775808);
}
}