use ::Data;
use collection::{Trace, TraceRef};
use collection::{LeastUpperBound, Lookup};
use collection::compact::Compact;
pub struct BasicTrace<K, T, V, L> {
phantom: ::std::marker::PhantomData<K>,
links: Vec<ListEntry>,
times: Vec<TimeEntry<T, V>>,
keys: L,
}
impl<K,V,L,T> Trace for BasicTrace<K, T, V, L>
where
K: Data,
V: Data,
L: Lookup<K, Offset>+'static,
T: LeastUpperBound+'static {
type Key = K;
type Index = T;
type Value = V;
#[inline(never)]
fn set_difference(&mut self, time: T, accumulation: Compact<K, V>) {
let keys = accumulation.keys;
let cnts = accumulation.cnts;
let vals = accumulation.vals;
let time_index = self.times.len();
let mut vals_offset = 0;
self.links.reserve(keys.len());
for (key, cnt) in keys.into_iter().zip(cnts.into_iter()) {
let next_position = Offset::new(self.links.len());
let prev_position = self.keys.entry_or_insert(key, || next_position);
if &prev_position.val() == &next_position.val() {
self.links.push(ListEntry {
time: time_index as u32,
vals: vals_offset,
next: None
});
}
else {
self.links.push(ListEntry {
time: time_index as u32,
vals: vals_offset,
next: Some(*prev_position)
});
*prev_position = next_position;
}
vals_offset += cnt;
}
self.times.push(TimeEntry { time: time, vals: vals });
}
}
impl<'a,K,V,L,T> TraceRef<'a,K,T,V> for &'a BasicTrace<K,T,V,L>
where K: Data+'a,
V: Data+'a,
L: Lookup<K, Offset>+'a,
T: LeastUpperBound+'a {
type VIterator = DifferenceIterator<'a, V>;
type TIterator = TraceIterator<'a,K,T,V,L>;
fn trace(self, key: &K) -> Self::TIterator {
TraceIterator {
trace: self,
next0: self.keys.get_ref(key).map(|&x|x),
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct Offset {
dataz: u32,
}
impl Offset {
#[inline(always)]
fn new(offset: usize) -> Offset {
assert!(offset < ((!0u32) as usize)); Offset { dataz: (!0u32) - offset as u32 }
}
#[inline(always)]
fn val(&self) -> usize { ((!0u32) - self.dataz) as usize }
}
struct ListEntry {
time: u32,
vals: u32,
next: Option<Offset>,
}
struct TimeEntry<T, V> {
time: T,
vals: Vec<(V, i32)>,
}
impl<K, V, L, T> BasicTrace<K, T, V, L> where K: Ord, V: Ord, L: Lookup<K, Offset>, T: LeastUpperBound {
#[inline]
fn get_range<'a>(&'a self, position: Offset) -> DifferenceIterator<'a, V> {
let time = self.links[position.val()].time as usize;
let vals_lower = self.links[position.val()].vals as usize;
let vals_upper = if (position.val() + 1) < self.links.len()
&& time == self.links[position.val() + 1].time as usize {
self.links[position.val() + 1].vals as usize
}
else {
self.times[time].vals.len()
};
DifferenceIterator::new(&self.times[time].vals[vals_lower..vals_upper])
}
}
impl<K: Eq, L: Lookup<K, Offset>, T, V> BasicTrace<K, T, V, L> {
pub fn new(l: L) -> BasicTrace<K, T, V, L> {
BasicTrace {
phantom: ::std::marker::PhantomData,
links: Vec::new(),
times: Vec::new(),
keys: l,
}
}
}
#[derive(Clone)]
pub struct TraceIterator<'a, K: Eq+'a, T: 'a, V: 'a, L: Lookup<K, Offset>+'a> {
trace: &'a BasicTrace<K, T, V, L>,
next0: Option<Offset>,
}
impl<'a, K, T, V, L> Iterator for TraceIterator<'a, K, T, V, L>
where K: Data,
T: LeastUpperBound+'a,
V: Data,
L: Lookup<K, Offset>+'a {
type Item = (&'a T, DifferenceIterator<'a, V>);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.next0.map(|position| {
let time_index = self.trace.links[position.val()].time as usize;
let result = (&self.trace.times[time_index].time, self.trace.get_range(position));
self.next0 = self.trace.links[position.val()].next;
result
})
}
}
pub struct DifferenceIterator<'a, V: 'a> {
vals: &'a [(V,i32)],
next: usize, }
impl<'a, V: 'a> DifferenceIterator<'a, V> {
fn new(vals: &'a [(V, i32)]) -> DifferenceIterator<'a, V> {
DifferenceIterator {
vals: vals,
next: 0,
}
}
}
impl<'a, V: 'a> Clone for DifferenceIterator<'a, V> {
fn clone(&self) -> Self {
DifferenceIterator {
vals: self.vals,
next: self.next,
}
}
}
impl<'a, V: 'a> Iterator for DifferenceIterator<'a, V> {
type Item = (&'a V, i32);
#[inline]
fn next(&mut self) -> Option<(&'a V, i32)> {
if self.next < self.vals.len() {
self.next += 1;
Some((&self.vals[self.next - 1].0, self.vals[self.next - 1].1))
}
else {
None
}
}
}