Skip to content

Commit 8013e37

Browse files
authored
Merge pull request #12 from segeljakt/rust-rfs
Rust implementation of Recalculate-From-Scratch (ReCalc)
2 parents ea8f488 + c683f9c commit 8013e37

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed

rust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ path = "src/lib.rs"
2121
num-traits = "0.2.12"
2222
arrayvec = "0.5.1"
2323
alga = "0.9.3"
24+
rand = "0.7.3"
2425

2526
[dev-dependencies]
2627
criterion = "0.3.3"

rust/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,6 @@ where
4040
/// Returns the aggregate of a subwindow.
4141
fn range_query(&self, range: Range<Time>) -> Value;
4242
}
43+
44+
/// Recalculate-From-Scratch
45+
pub mod recalc;

rust/src/recalc/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use crate::FifoWindow;
2+
use alga::general::AbstractMonoid;
3+
use alga::general::Operator;
4+
use std::marker::PhantomData;
5+
use std::collections::VecDeque;
6+
7+
#[derive(Debug)]
8+
pub struct ReCalc<Value, BinOp>
9+
where
10+
Value: AbstractMonoid<BinOp> + Clone,
11+
BinOp: Operator,
12+
{
13+
stack: VecDeque<Value>,
14+
op: PhantomData<BinOp>,
15+
}
16+
17+
impl<Value, BinOp> FifoWindow<Value, BinOp> for ReCalc<Value, BinOp>
18+
where
19+
Value: AbstractMonoid<BinOp> + Clone,
20+
BinOp: Operator,
21+
{
22+
fn new() -> ReCalc<Value, BinOp> {
23+
ReCalc {
24+
stack: VecDeque::new(),
25+
op: PhantomData,
26+
}
27+
}
28+
fn push(&mut self, v: Value) {
29+
self.stack.push_back(v);
30+
}
31+
fn pop(&mut self) {
32+
self.stack.pop_front();
33+
}
34+
fn query(&self) -> Value {
35+
self.stack
36+
.iter()
37+
.fold(Value::identity(), |acc, elem| acc.operate(&elem))
38+
}
39+
}

rust/tests/fifo-window.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
use alga::general::AbstractGroup;
2+
use alga::general::AbstractLoop;
3+
use alga::general::AbstractMagma;
4+
use alga::general::AbstractMonoid;
5+
use alga::general::AbstractQuasigroup;
6+
use alga::general::AbstractSemigroup;
7+
use alga::general::Identity;
8+
use alga::general::Operator;
9+
use alga::general::TwoSidedInverse;
10+
use rand::Rng;
11+
use swag::recalc::*;
12+
use swag::*;
13+
14+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
15+
struct Value(i32);
16+
17+
#[derive(Copy, Clone, Debug)]
18+
struct Sum;
19+
20+
impl Operator for Sum {
21+
fn operator_token() -> Sum {
22+
Sum
23+
}
24+
}
25+
26+
impl Identity<Sum> for Value {
27+
fn identity() -> Value {
28+
Value(0)
29+
}
30+
}
31+
32+
impl AbstractMagma<Sum> for Value {
33+
fn operate(&self, other: &Self) -> Self {
34+
Value(self.0 + other.0)
35+
}
36+
}
37+
38+
impl TwoSidedInverse<Sum> for Value {
39+
fn two_sided_inverse(&self) -> Value {
40+
Value(-self.0)
41+
}
42+
}
43+
44+
impl AbstractSemigroup<Sum> for Value {}
45+
impl AbstractMonoid<Sum> for Value {}
46+
impl AbstractQuasigroup<Sum> for Value {}
47+
impl AbstractLoop<Sum> for Value {}
48+
impl AbstractGroup<Sum> for Value {}
49+
50+
fn test1<Window>()
51+
where
52+
Window: FifoWindow<Value, Sum>,
53+
{
54+
let mut window = Window::new();
55+
56+
assert_eq!(window.query(), Value(0));
57+
58+
window.push(Value(1));
59+
60+
assert_eq!(window.query(), Value(1));
61+
62+
window.push(Value(2));
63+
64+
assert_eq!(window.query(), Value(3));
65+
66+
window.push(Value(3));
67+
68+
assert_eq!(window.query(), Value(6));
69+
70+
window.pop();
71+
72+
assert_eq!(window.query(), Value(5));
73+
}
74+
75+
fn test2<Window>()
76+
where
77+
Window: FifoWindow<Value, Sum>,
78+
{
79+
let mut window = Window::new();
80+
let mut rng = rand::thread_rng();
81+
let numbers: Vec<i32> = (0..1000).map(|_| rng.gen_range(1, 5)).collect();
82+
let sum: i32 = numbers.iter().sum();
83+
let values = numbers.into_iter().map(Value).collect::<Vec<Value>>();
84+
for v in values.clone() {
85+
window.push(v);
86+
}
87+
assert_eq!(window.query(), Value(sum));
88+
for _ in values {
89+
window.pop();
90+
}
91+
assert_eq!(window.query(), Value(0));
92+
}
93+
94+
#[test]
95+
fn test1_recalc() {
96+
test1::<ReCalc<Value, Sum>>();
97+
}
98+
99+
#[test]
100+
fn test2_recalc() {
101+
test2::<ReCalc<Value, Sum>>();
102+
}

0 commit comments

Comments
 (0)