use super::*;
use std::iter;
#[derive(Debug)]
pub struct Iterator {
index: u64,
offset: u64,
factor: u64,
}
impl Iterator {
#[inline]
pub fn new(index: u64) -> Self {
let mut instance = Self {
index: 0,
offset: 0,
factor: 0,
};
instance.seek(index);
instance
}
#[inline]
pub fn index(&self) -> u64 {
self.index
}
#[inline]
pub fn offset(&self) -> u64 {
self.offset
}
#[inline]
pub fn factor(&self) -> u64 {
self.factor
}
#[inline]
pub fn seek(&mut self, index: u64) {
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]
#[allow(clippy::comparison_chain)]
pub fn contains(&self, index: u64) -> bool {
if index > self.index {
index < (self.index + self.factor / 2)
} else if index < self.index {
let comp = self.factor / 2;
self.index < comp || index > (self.index - comp)
} else {
true
}
}
#[inline]
pub fn count_nodes(&self) -> u64 {
if is_even(self.index) {
1
} else {
self.factor - 1
}
}
#[inline]
pub fn count_leaves(&self) -> u64 {
(self.count_nodes() + 1) / 2
}
#[inline]
pub fn prev(&mut self) -> u64 {
if self.offset == 0 {
return self.index;
}
self.offset -= 1;
self.index -= self.factor;
self.index
}
#[inline]
pub fn sibling(&mut self) -> u64 {
if self.is_left() {
self.next().unwrap() } else {
self.prev()
}
}
#[inline]
pub fn parent(&mut self) -> u64 {
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) -> u64 {
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) -> u64 {
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) -> u64 {
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) -> u64 {
if self.factor == 2 {
return self.index;
}
self.factor /= 2;
self.index += self.factor / 2;
self.offset = 2 * self.offset + 1;
self.index
}
#[inline]
pub fn next_tree(&mut self) -> u64 {
self.index = self.index + self.factor / 2 + 1;
self.offset = self.index / 2;
self.factor = 2;
self.index
}
#[inline]
pub fn prev_tree(&mut self) -> u64 {
if self.offset == 0 {
self.index = 0;
self.factor = 2;
} else {
self.index = self.index - self.factor / 2 - 1;
self.offset = self.index / 2;
self.factor = 2;
}
self.index
}
#[inline]
pub fn full_root(&mut self, index: u64) -> bool {
if index <= self.index || is_odd(self.index) {
return false;
}
while index > self.index + self.factor + self.factor / 2 {
self.index += self.factor / 2;
self.factor *= 2;
self.offset /= 2;
}
true
}
}
impl iter::Iterator for Iterator {
type Item = u64;
#[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: u64) -> u64 {
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);
}
}