Skip to content

Commit a2ebe95

Browse files
committed
Add Rust implementation for DABA
1 parent c1748cd commit a2ebe95

File tree

3 files changed

+159
-6
lines changed

3 files changed

+159
-6
lines changed

rust/src/daba/mod.rs

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use crate::FifoWindow;
2+
use alga::general::AbstractMonoid;
3+
use alga::general::Operator;
4+
use std::collections::VecDeque;
5+
use std::marker::PhantomData;
6+
7+
#[derive(Clone)]
8+
pub struct DABA<Value, BinOp>
9+
where
10+
Value: AbstractMonoid<BinOp> + Clone,
11+
BinOp: Operator,
12+
{
13+
// ith oldest value in FIFO order stored at vi = vals[i]
14+
vals: VecDeque<Value>,
15+
aggs: VecDeque<Value>,
16+
// 0 ≤ l ≤ r ≤ a ≤ b ≤ aggs.len()
17+
l: usize, // Left, ∀p ∈ l...r−1 : aggs[p] = vals[p] ⊕ ... ⊕ vals[r−1]
18+
r: usize, // Right, ∀p ∈ r...a−1 : aggs[p] = vals[R] ⊕ ... ⊕ vals[p]
19+
a: usize, // Accum, ∀p ∈ a...b−1 : aggs[p] = vals[p] ⊕ ... ⊕ vals[b−1]
20+
b: usize, // Back, ∀p ∈ b...e−1 : aggs[p] = vals[B] ⊕ ... ⊕ vals[p]
21+
op: PhantomData<BinOp>,
22+
}
23+
24+
impl<Value, BinOp> FifoWindow<Value, BinOp> for DABA<Value, BinOp>
25+
where
26+
Value: AbstractMonoid<BinOp> + Clone,
27+
BinOp: Operator,
28+
{
29+
fn new() -> Self {
30+
Self {
31+
vals: VecDeque::new(),
32+
aggs: VecDeque::new(),
33+
l: 0,
34+
r: 0,
35+
a: 0,
36+
b: 0,
37+
op: PhantomData,
38+
}
39+
}
40+
fn push(&mut self, v: Value) {
41+
self.aggs.push_back(self.agg_b().operate(&v));
42+
self.vals.push_back(v);
43+
self.fixup();
44+
}
45+
fn pop(&mut self) {
46+
if self.vals.pop_front().is_some() {
47+
self.aggs.pop_front();
48+
self.l -= 1;
49+
self.r -= 1;
50+
self.a -= 1;
51+
self.b -= 1;
52+
self.fixup();
53+
}
54+
}
55+
fn query(&self) -> Value {
56+
self.agg_f().operate(&self.agg_b())
57+
}
58+
fn len(&self) -> usize {
59+
self.vals.len()
60+
}
61+
fn is_empty(&self) -> bool {
62+
self.vals.is_empty()
63+
}
64+
}
65+
66+
impl<Value, BinOp> DABA<Value, BinOp>
67+
where
68+
Value: AbstractMonoid<BinOp> + Clone,
69+
BinOp: Operator,
70+
{
71+
#[inline(always)]
72+
fn agg_f(&self) -> Value {
73+
if self.aggs.is_empty() {
74+
Value::identity()
75+
} else {
76+
self.aggs.front().unwrap().clone()
77+
}
78+
}
79+
#[inline(always)]
80+
fn agg_b(&self) -> Value {
81+
if self.b == self.aggs.len() {
82+
Value::identity()
83+
} else {
84+
self.aggs.back().unwrap().clone()
85+
}
86+
}
87+
#[inline(always)]
88+
fn agg_l(&self) -> Value {
89+
if self.l == self.r {
90+
Value::identity()
91+
} else {
92+
self.aggs[self.l].clone()
93+
}
94+
}
95+
#[inline(always)]
96+
fn agg_r(&self) -> Value {
97+
if self.r == self.a {
98+
Value::identity()
99+
} else {
100+
self.aggs[self.a - 1].clone()
101+
}
102+
}
103+
#[inline(always)]
104+
fn agg_a(&self) -> Value {
105+
if self.a == self.b {
106+
Value::identity()
107+
} else {
108+
self.aggs[self.a].clone()
109+
}
110+
}
111+
fn fixup(&mut self) {
112+
if self.b == 0 {
113+
self.singleton()
114+
} else {
115+
if self.l == self.b {
116+
self.flip()
117+
}
118+
if self.l == self.r {
119+
self.shift()
120+
} else {
121+
self.shrink()
122+
}
123+
}
124+
}
125+
#[inline(always)]
126+
fn singleton(&mut self) {
127+
self.l = self.aggs.len();
128+
self.r = self.l;
129+
self.a = self.l;
130+
self.b = self.l;
131+
}
132+
#[inline(always)]
133+
fn flip(&mut self) {
134+
self.l = 0;
135+
self.a = self.aggs.len();
136+
self.b = self.a;
137+
}
138+
#[inline(always)]
139+
fn shift(&mut self) {
140+
self.a += 1;
141+
self.r += 1;
142+
self.l += 1;
143+
}
144+
#[inline(always)]
145+
fn shrink(&mut self) {
146+
self.aggs[self.l] = self.agg_l().operate(&self.agg_r()).operate(&self.agg_a());
147+
self.l += 1;
148+
self.aggs[self.a - 1] = self.vals[self.a - 1].operate(&self.agg_a());
149+
self.a -= 1;
150+
}
151+
}

rust/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,5 @@ pub mod two_stacks;
5757
/// Reactive-Aggregator
5858
pub mod reactive;
5959

60+
/// De-Amortized Banker's Aggregator
61+
pub mod daba;

rust/tests/fifo_window.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ where
141141
}
142142

143143
test_matrix! {
144-
test1 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks ],
145-
test2 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks ],
146-
test3 => [ recalc::ReCalc, reactive::Reactive, two_stacks::TwoStacks ],
147-
test4 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks ],
148-
test5 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks ],
149-
test6 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks ]
144+
test1 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks, daba::DABA ],
145+
test2 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks, daba::DABA ],
146+
test3 => [ recalc::ReCalc, reactive::Reactive, two_stacks::TwoStacks, daba::DABA ],
147+
test4 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks, daba::DABA ],
148+
test5 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks, daba::DABA ],
149+
test6 => [ recalc::ReCalc, soe::SoE, reactive::Reactive, two_stacks::TwoStacks, daba::DABA ]
150150
}

0 commit comments

Comments
 (0)