use std::fmt::Debug;
use std::mem;
use leonardo::leonardo;
use subheap::SubHeapMut;
#[derive(Clone, Debug)]
pub struct Layout {
orders: u64,
size: usize,
}
impl Layout {
pub fn new() -> Self {
Layout {
orders: 0,
size: 0,
}
}
pub fn new_from_len(size: usize) -> Self {
let mut orders = 0;
let mut remaining = size;
for order in (0..63).rev() {
if leonardo(order) <= remaining {
remaining -= leonardo(order);
orders |= 1 << order;
}
}
Layout {
orders: orders,
size: size,
}
}
pub fn len(&self) -> usize {
self.size
}
pub fn push(&mut self) {
self.size += 1;
match self.lowest_order() {
Some(lowest_order) => {
let mergeable_mask : u64 = 3 << lowest_order;
if (mergeable_mask & self.orders) == mergeable_mask {
self.orders &= !mergeable_mask;
self.orders |= 1 << (lowest_order + 2);
} else if lowest_order == 1 {
self.orders |= 1;
} else {
self.orders |= 2;
}
}
None => {
self.orders |= 2;
}
}
}
pub fn pop(&mut self) {
if self.size == 0 {
return;
}
self.size -= 1;
match self.lowest_order() {
Some(lowest_order) => {
let mask : u64 = 1 << lowest_order;
self.orders &= !mask;
if lowest_order != 0 && lowest_order != 1 {
let mask : u64 = 3 << lowest_order - 2;
self.orders |= mask;
}
}
None => {}
}
}
#[inline]
pub fn lowest_order(&self) -> Option<u32> {
match self.orders.trailing_zeros() {
64 => None,
n => Some(n),
}
}
pub fn iter<'a, T : Ord + Debug>(&self, data : &'a mut [T]) -> IterMut<'a, T> {
assert_eq!(data.len(), self.size);
IterMut {
heap_data: data,
orders: self.orders,
}
}
}
#[derive(Debug)]
pub struct IterMut<'a, T: 'a> {
heap_data: &'a mut [T],
orders: u64,
}
impl<'a, T : Ord + Debug> Iterator for IterMut<'a, T>
{
type Item = SubHeapMut<'a, T>;
fn next(&mut self) -> Option<SubHeapMut<'a, T>> {
if self.orders != 0 {
let order = self.orders.trailing_zeros();
self.orders ^= 1 << order;
let heap_len = self.heap_data.len();
let mut heap_data = mem::replace(&mut self.heap_data, &mut []);
let (mut rest_data, mut subheap_data) = heap_data.split_at_mut(
heap_len - leonardo(order)
);
self.heap_data = rest_data;
Some(SubHeapMut::new(subheap_data, order))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let ones = self.orders.count_ones() as usize;
(ones, Some(ones))
}
}