use super::super::traits::binop;
use super::super::traits::fold;
use super::super::traits::push_pop;
use std::ops::RangeFull;
use binop::Monoid;
use fold::Fold;
use push_pop::{PopBack, PopFront, PushBack, PushFront};
#[derive(Clone, Debug)]
pub struct FoldableDeque<M: Monoid> {
buf_front: Vec<M::Set>,
buf_folded_front: Vec<M::Set>,
buf_back: Vec<M::Set>,
buf_folded_back: Vec<M::Set>,
monoid: M,
}
impl<M: Monoid> FoldableDeque<M>
where
M::Set: Clone,
{
#[must_use]
pub fn new() -> Self
where
M: Default,
{
Self::with(M::default())
}
#[must_use]
pub fn with(monoid: M) -> Self {
Self {
buf_front: vec![],
buf_folded_front: vec![monoid.id()],
buf_back: vec![],
buf_folded_back: vec![monoid.id()],
monoid,
}
}
fn rotate_to_front(&mut self) {
if !self.buf_front.is_empty() {
return;
}
let n = (self.buf_back.len() + 1) / 2;
let tmp_back = self.buf_back.split_off(n);
self.buf_front = self.buf_back.split_off(0);
self.buf_front.reverse();
self.buf_back = tmp_back;
self.build_folded();
}
fn rotate_to_back(&mut self) {
if !self.buf_back.is_empty() {
return;
}
let n = (self.buf_front.len() + 1) / 2;
let tmp_front = self.buf_front.split_off(n);
self.buf_back = self.buf_front.split_off(0);
self.buf_back.reverse();
self.buf_front = tmp_front;
self.build_folded();
}
fn build_folded(&mut self) {
{
let n = self.buf_front.len();
self.buf_folded_front = vec![self.monoid.id(); n + 1];
for i in 0..n {
self.buf_folded_front[i + 1] = self.monoid.op(
self.buf_front[i].clone(),
self.buf_folded_front[i].clone(),
);
}
}
{
let n = self.buf_back.len();
self.buf_folded_back = vec![self.monoid.id(); n + 1];
for i in 0..n {
self.buf_folded_back[i + 1] = self.monoid.op(
self.buf_folded_back[i].clone(),
self.buf_back[i].clone(),
);
}
}
}
}
impl<M: Monoid> PushBack for FoldableDeque<M>
where
M::Set: Clone,
{
type Input = M::Set;
fn push_back(&mut self, x: Self::Input) {
self.buf_back.push(x.clone());
self.buf_folded_back.push(
self.monoid.op(self.buf_folded_back.last().unwrap().clone(), x),
);
}
}
impl<M: Monoid> PushFront for FoldableDeque<M>
where
M::Set: Clone,
{
type Input = M::Set;
fn push_front(&mut self, x: Self::Input) {
self.buf_front.push(x.clone());
self.buf_folded_front.push(
self.monoid.op(x, self.buf_folded_front.last().unwrap().clone()),
);
}
}
impl<M: Monoid> PopBack for FoldableDeque<M>
where
M::Set: Clone,
{
type Output = M::Set;
fn pop_back(&mut self) -> Option<Self::Output> {
self.rotate_to_back();
if self.buf_folded_back.len() > 1 {
self.buf_folded_back.pop();
}
self.buf_back.pop()
}
}
impl<M: Monoid> PopFront for FoldableDeque<M>
where
M::Set: Clone,
{
type Output = M::Set;
fn pop_front(&mut self) -> Option<Self::Output> {
self.rotate_to_front();
if self.buf_folded_front.len() > 1 {
self.buf_folded_front.pop();
}
self.buf_front.pop()
}
}
impl<M: Monoid> Fold<RangeFull> for FoldableDeque<M>
where
M::Set: Clone,
{
type Output = M;
fn fold(&self, _: RangeFull) -> M::Set {
let front = self.buf_folded_front.last().unwrap().clone();
let back = self.buf_folded_back.last().unwrap().clone();
self.monoid.op(front, back)
}
}
impl<M: Monoid> Default for FoldableDeque<M>
where
M: Default,
M::Set: Clone,
{
fn default() -> Self { Self::new() }
}