use std::fmt::Debug;
use columnar::Columnar;
use crate::trace::implementations::{Layout, OffsetList};
use crate::difference::Semigroup;
use crate::lattice::Lattice;
use timely::progress::Timestamp;
pub struct ColumnarLayout<U: ColumnarUpdate> {
phantom: std::marker::PhantomData<U>,
}
impl<K, V, T, R> ColumnarUpdate for (K, V, T, R)
where
K: Columnar<Container: OrdContainer + Default> + Debug + Ord + Clone + 'static,
V: Columnar<Container: OrdContainer + Default> + Debug + Ord + Clone + 'static,
T: Columnar<Container: OrdContainer + Default> + Debug + Ord + Default + Clone + Lattice + Timestamp,
R: Columnar<Container: OrdContainer + Default> + Debug + Ord + Default + Semigroup + 'static,
{
type Key = K;
type Val = V;
type Time = T;
type Diff = R;
}
impl<U: ColumnarUpdate> Layout for ColumnarLayout<U> {
type KeyContainer = Coltainer<U::Key>;
type ValContainer = Coltainer<U::Val>;
type TimeContainer = Coltainer<U::Time>;
type DiffContainer = Coltainer<U::Diff>;
type OffsetContainer = OffsetList;
}
pub trait ColumnarUpdate : Debug + 'static {
type Key: Columnar<Container: OrdContainer + Default> + Debug + Ord + Clone + 'static;
type Val: Columnar<Container: OrdContainer + Default> + Debug + Ord + Clone + 'static;
type Time: Columnar<Container: OrdContainer + Default> + Debug + Ord + Default + Clone + Lattice + Timestamp;
type Diff: Columnar<Container: OrdContainer + Default> + Debug + Ord + Default + Semigroup + 'static;
}
pub trait OrdContainer : for<'a> columnar::Container<Ref<'a> : Ord> { }
impl<C: for<'a> columnar::Container<Ref<'a> : Ord>> OrdContainer for C { }
pub use batch_container::Coltainer;
mod batch_container {
use columnar::{Borrow, Columnar, Container, Clear, Push, Index, Len};
use crate::trace::implementations::BatchContainer;
pub struct Coltainer<C: Columnar> {
pub container: C::Container,
}
impl<C: Columnar> Default for Coltainer<C> {
fn default() -> Self { Self { container: Default::default() } }
}
impl<C: Columnar + Ord + Clone> BatchContainer for Coltainer<C> where for<'a> columnar::Ref<'a, C> : Ord {
type ReadItem<'a> = columnar::Ref<'a, C>;
type Owned = C;
#[inline(always)] fn into_owned<'a>(item: Self::ReadItem<'a>) -> Self::Owned { C::into_owned(item) }
#[inline(always)] fn clone_onto<'a>(item: Self::ReadItem<'a>, other: &mut Self::Owned) { other.copy_from(item) }
#[inline(always)] fn push_ref(&mut self, item: Self::ReadItem<'_>) { self.container.push(item) }
#[inline(always)] fn push_own(&mut self, item: &Self::Owned) { self.container.push(item) }
fn clear(&mut self) { self.container.clear() }
fn with_capacity(_size: usize) -> Self { Self::default() }
fn merge_capacity(cont1: &Self, cont2: &Self) -> Self {
Self {
container: <C as Columnar>::Container::with_capacity_for([cont1.container.borrow(), cont2.container.borrow()].into_iter()),
}
}
#[inline(always)] fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> { columnar::ContainerOf::<C>::reborrow_ref(item) }
#[inline(always)] fn index(&self, index: usize) -> Self::ReadItem<'_> { self.container.borrow().get(index) }
#[inline(always)] fn len(&self) -> usize { self.container.len() }
fn advance<F: for<'a> Fn(Self::ReadItem<'a>)->bool>(&self, start: usize, end: usize, function: F) -> usize {
let borrow = self.container.borrow();
let small_limit = 8;
if end > start + small_limit && function(borrow.get(start + small_limit)) {
let mut index = small_limit + 1;
if start + index < end && function(borrow.get(start + index)) {
let mut step = 1;
while start + index + step < end && function(borrow.get(start + index + step)) {
index += step;
step <<= 1;
}
step >>= 1;
while step > 0 {
if start + index + step < end && function(borrow.get(start + index + step)) {
index += step;
}
step >>= 1;
}
index += 1;
}
index
}
else {
let limit = std::cmp::min(end, start + small_limit);
(start .. limit).filter(|x| function(borrow.get(*x))).count()
}
}
}
}