Skip to content

Commit eddc8b4

Browse files
committed
added ArqView for ergonomics
1 parent a713edb commit eddc8b4

File tree

1 file changed

+65
-69
lines changed

1 file changed

+65
-69
lines changed

src/arq_tree.rs

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ impl<T: ArqSpec> DynamicArqNode<T> {
168168
}
169169
}
170170

171+
type ArqView = (usize, i64, i64);
172+
171173
/// A dynamic, and optionally persistent, associate range query data structure.
172174
pub struct DynamicArq<T: ArqSpec> {
173-
l_bound: i64,
174-
r_bound: i64,
175175
nodes: Vec<DynamicArqNode<T>>,
176176
is_persistent: bool,
177177
initializer: Box<dyn Fn(i64, i64) -> T::M>,
@@ -183,24 +183,24 @@ impl<T: ArqSpec> DynamicArq<T> {
183183
r_bound: i64,
184184
is_persistent: bool,
185185
initializer: Box<dyn Fn(i64, i64) -> T::M>,
186-
) -> Self {
186+
) -> (Self, ArqView) {
187187
let val = initializer(l_bound, r_bound);
188188
let nodes = vec![DynamicArqNode::new(val)];
189-
Self {
190-
l_bound,
191-
r_bound,
189+
let arq = Self {
192190
nodes,
193191
is_persistent,
194192
initializer,
195-
}
193+
};
194+
let root_view = (0, l_bound, r_bound);
195+
(arq, root_view)
196196
}
197197

198-
pub fn new_with_identity(l_bound: i64, r_bound: i64, is_persistent: bool) -> Self {
198+
pub fn new_with_identity(l_bound: i64, r_bound: i64, is_persistent: bool) -> (Self, ArqView) {
199199
let initializer = Box::new(|_, _| T::identity());
200200
Self::new(l_bound, r_bound, is_persistent, initializer)
201201
}
202202

203-
fn push(&mut self, p: usize, l: i64, r: i64) -> (usize, usize) {
203+
fn push(&mut self, (p, l, r): ArqView) -> (ArqView, ArqView) {
204204
let m = (l + r) / 2;
205205
let (lp, rp) = match self.nodes[p].down {
206206
Some(children) => children,
@@ -216,7 +216,7 @@ impl<T: ArqSpec> DynamicArq<T> {
216216
self.nodes[lp].apply(f, l == m);
217217
self.nodes[rp].apply(f, m + 1 == r);
218218
}
219-
(lp, rp)
219+
((lp, l, m), (rp, m + 1, r))
220220
}
221221

222222
fn pull(&mut self, p: usize) {
@@ -236,49 +236,41 @@ impl<T: ArqSpec> DynamicArq<T> {
236236
}
237237
}
238238

239-
fn m_helper(&mut self, p: usize, l: i64, r: i64, f: &T::F, cl: i64, cr: i64) -> usize {
239+
/// Applies the endomorphism f to all entries from l to r, inclusive.
240+
/// If l == r, the updates are eager. Otherwise, they are lazy.
241+
pub fn modify(&mut self, view: ArqView, l: i64, r: i64, f: &T::F) -> ArqView {
242+
let (p, cl, cr) = view;
240243
if r < cl || cr < l {
241-
p
244+
view
242245
} else if l <= cl && cr <= r /* && self.l == self.r forces eager */ {
243246
let p_clone = self.clone_node(p);
244247
self.nodes[p_clone].apply(f, l == r);
245-
p_clone
248+
(p_clone, cl, cr)
246249
} else {
247-
let (lp, rp) = self.push(p, cl, cr);
248-
let cm = (cl + cr) / 2;
250+
let (l_view, r_view) = self.push(view);
249251
let p_clone = self.clone_node(p);
250-
let lp_clone = self.m_helper(lp, l, r, f, cl, cm);
251-
let rp_clone = self.m_helper(rp, l, r, f, cm + 1, cr);
252+
let lp_clone = self.modify(l_view, l, r, f).0;
253+
let rp_clone = self.modify(r_view, l, r, f).0;
252254
self.nodes[p_clone].down = Some((lp_clone, rp_clone));
253255
self.pull(p_clone);
254-
p_clone
256+
(p_clone, cl, cr)
255257
}
256258
}
257259

258-
fn q_helper(&mut self, p: usize, l: i64, r: i64, cl: i64, cr: i64) -> T::M {
260+
/// Returns the aggregate range query on all entries from l to r, inclusive.
261+
pub fn query(&mut self, view: ArqView, l: i64, r: i64) -> T::M {
262+
let (p, cl, cr) = view;
259263
if r < cl || cr < l {
260264
T::identity()
261265
} else if l <= cl && cr <= r {
262266
T::op(&T::identity(), &self.nodes[p].val)
263267
} else {
264-
let (lp, rp) = self.push(p, cl, cr);
265-
let cm = (cl + cr) / 2;
266-
let l_agg = self.q_helper(lp, l, r, cl, cm);
267-
let r_agg = self.q_helper(rp, l, r, cm + 1, cr);
268+
let (l_view, r_view) = self.push(view);
269+
let l_agg = self.query(l_view, l, r);
270+
let r_agg = self.query(r_view, l, r);
268271
T::op(&l_agg, &r_agg)
269272
}
270273
}
271-
272-
/// Applies the endomorphism f to all entries from l to r, inclusive.
273-
/// If l == r, the updates are eager. Otherwise, they are lazy.
274-
pub fn modify(&mut self, p: usize, l: i64, r: i64, f: &T::F) -> usize {
275-
self.m_helper(p, l, r, f, self.l_bound, self.r_bound)
276-
}
277-
278-
/// Returns the aggregate range query on all entries from l to r, inclusive.
279-
pub fn query(&mut self, p: usize, l: i64, r: i64) -> T::M {
280-
self.q_helper(p, l, r, self.l_bound, self.r_bound)
281-
}
282274
}
283275

284276
pub trait ArqSpec {
@@ -351,18 +343,19 @@ pub fn first_negative_static(arq: &mut StaticArq<AssignMin>) -> i32 {
351343

352344
/// An example of binary search on the tree of a DynamicArq.
353345
/// The tree may have any size, not necessarily a power of two.
354-
pub fn first_negative_dynamic(arq: &mut DynamicArq<AssignMin>, p: usize, cl: i64, cr: i64) -> i64 {
346+
pub fn first_negative_dynamic(arq: &mut DynamicArq<AssignMin>, view: ArqView) -> i64 {
347+
let (p, cl, cr) = view;
355348
if arq.nodes[p].val >= 0 {
356349
-1
357350
} else if cl == cr {
358351
cl
359352
} else {
360-
let (lp, rp) = arq.push(p, cl, cr);
361-
let cm = (cl + cr) / 2;
353+
let (l_view, r_view) = arq.push(view);
354+
let lp = l_view.0;
362355
if arq.nodes[lp].val < 0 {
363-
first_negative_dynamic(arq, lp, cl, cm)
356+
first_negative_dynamic(arq, l_view)
364357
} else {
365-
first_negative_dynamic(arq, rp, cm + 1, cr)
358+
first_negative_dynamic(arq, r_view)
366359
}
367360
}
368361
}
@@ -554,31 +547,31 @@ mod test {
554547
#[test]
555548
fn test_dynamic_rmq() {
556549
let initializer = Box::new(|_, _| 0);
557-
let mut arq = DynamicArq::<AssignMin>::new(0, 9, false, initializer);
550+
let (mut arq, view) = DynamicArq::<AssignMin>::new(0, 9, false, initializer);
558551

559-
assert_eq!(arq.query(0, 0, 9), 0);
552+
assert_eq!(arq.query(view, 0, 9), 0);
560553

561-
arq.modify(0, 2, 4, &-5);
562-
arq.modify(0, 5, 7, &-3);
563-
arq.modify(0, 1, 6, &1);
554+
arq.modify(view, 2, 4, &-5);
555+
arq.modify(view, 5, 7, &-3);
556+
arq.modify(view, 1, 6, &1);
564557

565-
assert_eq!(arq.query(0, 0, 9), -3);
558+
assert_eq!(arq.query(view, 0, 9), -3);
566559
}
567560

568561
#[test]
569562
fn test_persistent_rmq() {
570563
let initializer = Box::new(|_, _| 0);
571-
let mut arq = DynamicArq::<AssignMin>::new(0, 9, true, initializer);
564+
let (mut arq, mut view) = DynamicArq::<AssignMin>::new(0, 9, true, initializer);
572565

573-
let mut p = 0;
574-
p = arq.modify(p, 2, 4, &-5);
575-
let snapshot = p;
576-
p = arq.modify(p, 5, 7, &-3);
577-
p = arq.modify(p, 1, 6, &1);
566+
let at_init = view;
567+
view = arq.modify(view, 2, 4, &-5);
568+
let snapshot = view;
569+
view = arq.modify(view, 5, 7, &-3);
570+
view = arq.modify(view, 1, 6, &1);
578571

579-
assert_eq!(arq.query(0, 0, 9), 0);
572+
assert_eq!(arq.query(at_init, 0, 9), 0);
580573
assert_eq!(arq.query(snapshot, 0, 9), -5);
581-
assert_eq!(arq.query(p, 0, 9), -3);
574+
assert_eq!(arq.query(view, 0, 9), -3);
582575
}
583576

584577
#[test]
@@ -597,15 +590,15 @@ mod test {
597590
#[test]
598591
fn test_dynamic_range_sum() {
599592
let initializer = Box::new(|l, r| (0, 1 + r - l));
600-
let mut arq = DynamicArq::<AssignSum>::new(0, 9, false, initializer);
593+
let (mut arq, view) = DynamicArq::<AssignSum>::new(0, 9, false, initializer);
601594

602-
assert_eq!(arq.query(0, 0, 9), (0, 10));
595+
assert_eq!(arq.query(view, 0, 9), (0, 10));
603596

604-
arq.modify(0, 1, 3, &10);
605-
arq.modify(0, 3, 5, &1);
597+
arq.modify(view, 1, 3, &10);
598+
arq.modify(view, 3, 5, &1);
606599

607-
assert_eq!(arq.query(0, 0, 9), (23, 10));
608-
assert_eq!(arq.query(0, 10, 4), (0, 0));
600+
assert_eq!(arq.query(view, 0, 9), (23, 10));
601+
assert_eq!(arq.query(view, 10, 4), (0, 0));
609602
}
610603

611604
#[test]
@@ -621,13 +614,13 @@ mod test {
621614

622615
#[test]
623616
fn test_dynamic_supply_demand() {
624-
let mut arq = DynamicArq::<SupplyDemand>::new_with_identity(0, 9, false);
617+
let (mut arq, view) = DynamicArq::<SupplyDemand>::new_with_identity(0, 9, false);
625618

626-
arq.modify(0, 1, 1, &(25, 100));
627-
arq.modify(0, 3, 3, &(100, 30));
628-
arq.modify(0, 9, 9, &(0, 20));
619+
arq.modify(view, 1, 1, &(25, 100));
620+
arq.modify(view, 3, 3, &(100, 30));
621+
arq.modify(view, 9, 9, &(0, 20));
629622

630-
assert_eq!(arq.query(0, 0, 9), (125, 150, 75));
623+
assert_eq!(arq.query(view, 0, 9), (125, 150, 75));
631624
}
632625

633626
#[test]
@@ -646,14 +639,17 @@ mod test {
646639
#[test]
647640
fn test_dynamic_binary_search_rmq() {
648641
let initializer = Box::new(|_, r| 2 - r);
649-
let (l_bound, r_bound) = (0, 7);
650-
let mut arq = DynamicArq::<AssignMin>::new(l_bound, r_bound, false, initializer);
651-
let pos = first_negative_dynamic(&mut arq, 0, l_bound, r_bound);
642+
let (l_bound, r_bound) = (0, 1_000_000_000_000_000_000);
643+
let (mut arq, view) = DynamicArq::<AssignMin>::new(l_bound, r_bound, false, initializer);
644+
let pos = first_negative_dynamic(&mut arq, view);
652645

653-
arq.modify(0, 2, 7, &0);
654-
let pos_zeros = first_negative_dynamic(&mut arq, 0, l_bound, r_bound);
646+
arq.modify(view, 2, r_bound - 1, &0);
647+
let pos_mostly_zeros = first_negative_dynamic(&mut arq, view);
648+
arq.modify(view, 2, r_bound, &0);
649+
let pos_zeros = first_negative_dynamic(&mut arq, view);
655650

656651
assert_eq!(pos, 3);
652+
assert_eq!(pos_mostly_zeros, r_bound);
657653
assert_eq!(pos_zeros, -1);
658654
}
659655

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy