From 5a37cf8a31c4d4eeb1805eb3e90894b8e67d16c8 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 01/11] deque: Fix grow condition in add_front Without this, it will hit the assert in fn grow after 32 consecutive add_front. --- src/libextra/deque.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index e89c12e5848de..bc4d365e4488c 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -107,7 +107,7 @@ impl Deque { if self.lo == 0u { self.lo = self.elts.len() - 1u; } else { self.lo -= 1u; } - if self.lo == self.hi { + if self.nelts == self.elts.len() { self.elts = grow(self.nelts, oldlo, self.elts); self.lo = self.elts.len() - 1u; self.hi = self.nelts; From 81933edf92afda59ea41ec3692ab43759285b731 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 02/11] deque: Add tests and bench tests Add a test that excercises deque growing. Add bench tests for grow, new, add_back, add_front, to expose how slow these functions are. --- src/libextra/deque.rs | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index bc4d365e4488c..a07d9e6fd22a4 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -256,6 +256,7 @@ mod tests { use std::cmp::Eq; use std::kinds::Copy; use std::int; + use extra::test; #[test] fn test_simple() { @@ -369,6 +370,61 @@ mod tests { assert_eq!(copy *deq.get(3), copy d); } + #[test] + fn test_add_front_grow() { + let mut deq = Deque::new(); + for int::range(0, 66) |i| { + deq.add_front(i); + } + assert_eq!(deq.len(), 66); + + for int::range(0, 66) |i| { + assert_eq!(*deq.get(i), 65 - i); + } + + let mut deq = Deque::new(); + for int::range(0, 66) |i| { + deq.add_back(i); + } + + for int::range(0, 66) |i| { + assert_eq!(*deq.get(i), i); + } + } + + #[bench] + fn bench_new(b: &mut test::BenchHarness) { + do b.iter { + let _ = Deque::new::(); + } + } + + #[bench] + fn bench_add_back(b: &mut test::BenchHarness) { + let mut deq = Deque::new(); + do b.iter { + deq.add_back(0); + } + } + + #[bench] + fn bench_add_front(b: &mut test::BenchHarness) { + let mut deq = Deque::new(); + do b.iter { + deq.add_front(0); + } + } + + #[bench] + fn bench_grow(b: &mut test::BenchHarness) { + let mut deq = Deque::new(); + do b.iter { + for 65.times { + deq.add_front(1); + } + } + } + #[deriving(Eq)] enum Taggy { One(int), Two(int, int), Three(int, int, int), } From 40ce0b7d76fe39c58e4bdf119af33c4d24950077 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 03/11] deque: Speed up deque growth by a lot Fix some issues with the deque being very slow, keep the same vec around instead of constructing a new. Move as few elements as possible, so the self.lo point is not moved after grow. [o o o o o|o o o] hi...^ ^.... lo grows to [. . . . .|o o o o o o o o|. . .] ^.. lo ^.. hi If the deque is append-only, it will result in moving no elements on grow. If the deque is prepend-only, all will be moved each time. The bench tests added show big improvements: Timed using `rust build -O --test extra.rs && ./extra --bench deque` Old version: test deque::tests::bench_add_back ... bench: 4976 ns/iter (+/- 9) test deque::tests::bench_add_front ... bench: 4108 ns/iter (+/- 18) test deque::tests::bench_grow ... bench: 416964 ns/iter (+/- 4197) test deque::tests::bench_new ... bench: 408 ns/iter (+/- 12) With this commit: test deque::tests::bench_add_back ... bench: 12 ns/iter (+/- 0) test deque::tests::bench_add_front ... bench: 16 ns/iter (+/- 0) test deque::tests::bench_grow ... bench: 1515 ns/iter (+/- 30) test deque::tests::bench_new ... bench: 419 ns/iter (+/- 3) --- src/libextra/deque.rs | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index a07d9e6fd22a4..02d3e81148f17 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -11,7 +11,6 @@ //! A double-ended queue implemented as a circular buffer use std::uint; -use std::util::replace; use std::vec; use std::cast::transmute; @@ -103,15 +102,13 @@ impl Deque { /// Prepend an element to the deque pub fn add_front(&mut self, t: T) { - let oldlo = self.lo; + if self.nelts == self.elts.len() { + grow(self.nelts, self.lo, &mut self.elts); + self.hi = self.lo + self.nelts; + } if self.lo == 0u { self.lo = self.elts.len() - 1u; } else { self.lo -= 1u; } - if self.nelts == self.elts.len() { - self.elts = grow(self.nelts, oldlo, self.elts); - self.lo = self.elts.len() - 1u; - self.hi = self.nelts; - } self.elts[self.lo] = Some(t); self.nelts += 1u; } @@ -119,12 +116,14 @@ impl Deque { /// Append an element to the deque pub fn add_back(&mut self, t: T) { if self.lo == self.hi && self.nelts != 0u { - self.elts = grow(self.nelts, self.lo, self.elts); - self.lo = 0u; - self.hi = self.nelts; + grow(self.nelts, self.lo, &mut self.elts); + self.hi = self.lo + self.nelts; } self.elts[self.hi] = Some(t); - self.hi = (self.hi + 1u) % self.elts.len(); + self.hi += 1; + if self.hi == self.elts.len() { + self.hi = 0; + } self.nelts += 1u; } @@ -235,15 +234,19 @@ iterator!{impl DequeMutRevIterator -> &'self mut T, -1} /// Grow is only called on full elts, so nelts is also len(elts), unlike /// elsewhere. -fn grow(nelts: uint, lo: uint, elts: &mut [Option]) -> ~[Option] { +fn grow(nelts: uint, lo: uint, elts: &mut ~[Option]) { assert_eq!(nelts, elts.len()); - let mut rv = ~[]; + let newlen = elts.capacity() * 2; + elts.reserve(newlen); - do rv.grow_fn(nelts + 1) |i| { - replace(&mut elts[(lo + i) % nelts], None) + /* fill with None */ + for uint::range(elts.len(), elts.capacity()) |_| { + elts.push(None); + } + /* move the former wraparound to the new half */ + for uint::range(0, lo) |i| { + elts.swap(i, nelts + i); } - - rv } fn get<'r, T>(elts: &'r [Option], i: uint) -> &'r T { From 08dc72f5d54d3385d2a772b0ce2c92459ff25bfd Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 04/11] deque: Implement FromIterator So that deque can be used with IteratorUtil::collect() --- src/libextra/deque.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index 02d3e81148f17..3710f089e2f73 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -13,6 +13,7 @@ use std::uint; use std::vec; use std::cast::transmute; +use std::iterator::FromIterator; static INITIAL_CAPACITY: uint = 32u; // 2^5 @@ -253,6 +254,16 @@ fn get<'r, T>(elts: &'r [Option], i: uint) -> &'r T { match elts[i] { Some(ref t) => t, _ => fail!() } } +impl> FromIterator for Deque { + fn from_iterator(iterator: &mut T) -> Deque { + let mut deq = Deque::new(); + for iterator.advance |elt| { + deq.add_back(elt); + } + deq + } +} + #[cfg(test)] mod tests { use super::*; @@ -545,4 +556,20 @@ mod tests { } assert_eq!(d.rev_iter().collect::<~[&int]>(), ~[&4,&3,&2,&1,&0,&6,&7,&8]); } + + #[test] + fn test_from_iterator() { + use std::iterator; + let v = ~[1,2,3,4,5,6,7]; + let deq: Deque = v.iter().transform(|&x| x).collect(); + let u: ~[int] = deq.iter().transform(|&x| x).collect(); + assert_eq!(u, v); + + let mut seq = iterator::Counter::new(0u, 2).take_(256); + let deq: Deque = seq.collect(); + for deq.iter().enumerate().advance |(i, &x)| { + assert_eq!(2*i, x); + } + assert_eq!(deq.len(), 256); + } } From 5d72f3f296b7815a4e8ec7b6b3e03bd7a4ed47ba Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 05/11] deque: Remove rendundant field hi The deque is determined by vec self.elts.len(), self.nelts, and self.lo, and self.hi is calculated from these. self.hi is just the raw index of element number `self.nelts` --- src/libextra/deque.rs | 48 +++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index 3710f089e2f73..04941e9886e2e 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -21,7 +21,6 @@ static INITIAL_CAPACITY: uint = 32u; // 2^5 pub struct Deque { priv nelts: uint, priv lo: uint, - priv hi: uint, priv elts: ~[Option] } @@ -39,26 +38,31 @@ impl Mutable for Deque { for self.elts.mut_iter().advance |x| { *x = None } self.nelts = 0; self.lo = 0; - self.hi = 0; } } impl Deque { /// Create an empty Deque pub fn new() -> Deque { - Deque{nelts: 0, lo: 0, hi: 0, + Deque{nelts: 0, lo: 0, elts: vec::from_fn(INITIAL_CAPACITY, |_| None)} } /// Return a reference to the first element in the deque /// /// Fails if the deque is empty - pub fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) } + pub fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.raw_index(0)) } /// Return a reference to the last element in the deque /// /// Fails if the deque is empty - pub fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) } + pub fn peek_back<'a>(&'a self) -> &'a T { + if self.nelts > 0 { + get(self.elts, self.raw_index(self.nelts - 1)) + } else { + fail!("peek_back: empty deque"); + } + } /// Retrieve an element in the deque by index /// @@ -88,24 +92,28 @@ impl Deque { result } + /// Return index in underlying vec for element index + fn raw_index(&self, idx: uint) -> uint { + if self.lo >= self.elts.len() - idx { + (self.lo + idx) - self.elts.len() + } else { + (self.lo + idx) + } + } + /// Remove and return the last element in the deque /// /// Fails if the deque is empty pub fn pop_back(&mut self) -> T { - if self.hi == 0u { - self.hi = self.elts.len() - 1u; - } else { self.hi -= 1u; } - let result = self.elts[self.hi].swap_unwrap(); - self.elts[self.hi] = None; - self.nelts -= 1u; - result + self.nelts -= 1; + let hi = self.raw_index(self.nelts); + self.elts[hi].swap_unwrap() } /// Prepend an element to the deque pub fn add_front(&mut self, t: T) { if self.nelts == self.elts.len() { grow(self.nelts, self.lo, &mut self.elts); - self.hi = self.lo + self.nelts; } if self.lo == 0u { self.lo = self.elts.len() - 1u; @@ -116,15 +124,11 @@ impl Deque { /// Append an element to the deque pub fn add_back(&mut self, t: T) { - if self.lo == self.hi && self.nelts != 0u { + if self.nelts == self.elts.len() { grow(self.nelts, self.lo, &mut self.elts); - self.hi = self.lo + self.nelts; - } - self.elts[self.hi] = Some(t); - self.hi += 1; - if self.hi == self.elts.len() { - self.hi = 0; } + let hi = self.raw_index(self.nelts); + self.elts[hi] = Some(t); self.nelts += 1u; } @@ -165,12 +169,12 @@ impl Deque { /// Back-to-front iterator. pub fn rev_iter<'a>(&'a self) -> DequeRevIterator<'a, T> { - DequeRevIterator { idx: self.hi - 1u, nelts: self.nelts, used: 0, vec: self.elts } + DequeRevIterator { idx: self.raw_index(self.nelts-1), nelts: self.nelts, used: 0, vec: self.elts } } /// Back-to-front iterator which returns mutable values. pub fn mut_rev_iter<'a>(&'a mut self) -> DequeMutRevIterator<'a, T> { - DequeMutRevIterator { idx: self.hi - 1u, nelts: self.nelts, used: 0, vec: self.elts } + DequeMutRevIterator { idx: self.raw_index(self.nelts-1), nelts: self.nelts, used: 0, vec: self.elts } } } From f88d532734dbddecf81bc1d0ce51d30cb9fc9731 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 06/11] deque: Add tests for mut_iter and mut_rev_iter --- src/libextra/deque.rs | 52 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index 04941e9886e2e..bd7b9d5b51d1c 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -273,7 +273,7 @@ mod tests { use super::*; use std::cmp::Eq; use std::kinds::Copy; - use std::int; + use std::{int, uint}; use extra::test; #[test] @@ -536,6 +536,8 @@ mod tests { #[test] fn test_iter() { let mut d = Deque::new(); + assert_eq!(d.iter().next(), None); + for int::range(0,5) |i| { d.add_back(i); } @@ -550,6 +552,8 @@ mod tests { #[test] fn test_rev_iter() { let mut d = Deque::new(); + assert_eq!(d.rev_iter().next(), None); + for int::range(0,5) |i| { d.add_back(i); } @@ -561,6 +565,52 @@ mod tests { assert_eq!(d.rev_iter().collect::<~[&int]>(), ~[&4,&3,&2,&1,&0,&6,&7,&8]); } + #[test] + fn test_mut_iter() { + let mut d = Deque::new(); + assert!(d.mut_iter().next().is_none()); + + for uint::range(0,3) |i| { + d.add_front(i); + } + + for d.mut_iter().enumerate().advance |(i, elt)| { + assert_eq!(*elt, 2 - i); + *elt = i; + } + + { + let mut it = d.mut_iter(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } + } + + #[test] + fn test_mut_rev_iter() { + let mut d = Deque::new(); + assert!(d.mut_rev_iter().next().is_none()); + + for uint::range(0,3) |i| { + d.add_front(i); + } + + for d.mut_rev_iter().enumerate().advance |(i, elt)| { + assert_eq!(*elt, i); + *elt = i; + } + + { + let mut it = d.mut_rev_iter(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } + } + #[test] fn test_from_iterator() { use std::iterator; From 75015c36f9fa6d0958874c1a448d6d67056145ae Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 07/11] deque: Change iterators to use the same index calculation as Deque The previous implementation of reverse iterators used modulus (%) of negative indices, which did work but was fragile due to dependency on the divisor. --- src/libextra/deque.rs | 78 +++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index bd7b9d5b51d1c..e8f8a31d7be0b 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -12,7 +12,6 @@ use std::uint; use std::vec; -use std::cast::transmute; use std::iterator::FromIterator; static INITIAL_CAPACITY: uint = 32u; // 2^5 @@ -92,13 +91,9 @@ impl Deque { result } - /// Return index in underlying vec for element index + /// Return index in underlying vec for a given logical element index fn raw_index(&self, idx: uint) -> uint { - if self.lo >= self.elts.len() - idx { - (self.lo + idx) - self.elts.len() - } else { - (self.lo + idx) - } + raw_index(self.lo, self.elts.len(), idx) } /// Remove and return the last element in the deque @@ -159,42 +154,39 @@ impl Deque { /// Front-to-back iterator. pub fn iter<'a>(&'a self) -> DequeIterator<'a, T> { - DequeIterator { idx: self.lo, nelts: self.nelts, used: 0, vec: self.elts } + DequeIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo} } /// Front-to-back iterator which returns mutable values. pub fn mut_iter<'a>(&'a mut self) -> DequeMutIterator<'a, T> { - DequeMutIterator { idx: self.lo, nelts: self.nelts, used: 0, vec: self.elts } + DequeMutIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo} } /// Back-to-front iterator. pub fn rev_iter<'a>(&'a self) -> DequeRevIterator<'a, T> { - DequeRevIterator { idx: self.raw_index(self.nelts-1), nelts: self.nelts, used: 0, vec: self.elts } + DequeRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts, + lo: self.lo} } /// Back-to-front iterator which returns mutable values. pub fn mut_rev_iter<'a>(&'a mut self) -> DequeMutRevIterator<'a, T> { - DequeMutRevIterator { idx: self.raw_index(self.nelts-1), nelts: self.nelts, used: 0, vec: self.elts } + DequeMutRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts, + lo: self.lo} } } macro_rules! iterator { - (impl $name:ident -> $elem:ty, $step:expr) => { + (impl $name:ident -> $elem:ty, $getter:ident, $step:expr) => { impl<'self, T> Iterator<$elem> for $name<'self, T> { #[inline] fn next(&mut self) -> Option<$elem> { - if self.used >= self.nelts { + if self.nelts == 0 { return None; } - let ret = unsafe { - match self.vec[self.idx % self.vec.len()] { - Some(ref e) => Some(transmute(e)), - None => None - } - }; - self.idx += $step; - self.used += 1; - ret + let raw_index = raw_index(self.lo, self.elts.len(), self.index); + self.index += $step; + self.nelts -= 1; + Some(self.elts[raw_index]. $getter ()) } } } @@ -202,40 +194,39 @@ macro_rules! iterator { /// Deque iterator pub struct DequeIterator<'self, T> { - priv idx: uint, + priv lo: uint, priv nelts: uint, - priv used: uint, - priv vec: &'self [Option] + priv index: uint, + priv elts: &'self [Option], } -iterator!{impl DequeIterator -> &'self T, 1} +iterator!{impl DequeIterator -> &'self T, get_ref, 1} /// Deque reverse iterator pub struct DequeRevIterator<'self, T> { - priv idx: uint, + priv lo: uint, priv nelts: uint, - priv used: uint, - priv vec: &'self [Option] + priv index: uint, + priv elts: &'self [Option], } -iterator!{impl DequeRevIterator -> &'self T, -1} +iterator!{impl DequeRevIterator -> &'self T, get_ref, -1} /// Deque mutable iterator pub struct DequeMutIterator<'self, T> { - priv idx: uint, + priv lo: uint, priv nelts: uint, - priv used: uint, - priv vec: &'self mut [Option] - + priv index: uint, + priv elts: &'self mut [Option], } -iterator!{impl DequeMutIterator -> &'self mut T, 1} +iterator!{impl DequeMutIterator -> &'self mut T, get_mut_ref, 1} /// Deque mutable reverse iterator pub struct DequeMutRevIterator<'self, T> { - priv idx: uint, + priv lo: uint, priv nelts: uint, - priv used: uint, - priv vec: &'self mut [Option] + priv index: uint, + priv elts: &'self mut [Option], } -iterator!{impl DequeMutRevIterator -> &'self mut T, -1} +iterator!{impl DequeMutRevIterator -> &'self mut T, get_mut_ref, -1} /// Grow is only called on full elts, so nelts is also len(elts), unlike /// elsewhere. @@ -258,6 +249,15 @@ fn get<'r, T>(elts: &'r [Option], i: uint) -> &'r T { match elts[i] { Some(ref t) => t, _ => fail!() } } +/// Return index in underlying vec for a given logical element index +fn raw_index(lo: uint, len: uint, index: uint) -> uint { + if lo >= len - index { + lo + index - len + } else { + lo + index + } +} + impl> FromIterator for Deque { fn from_iterator(iterator: &mut T) -> Deque { let mut deq = Deque::new(); From 8a3267672c43e7cc116e588dd21998d14fc21ba4 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 08/11] deque: Move the shorter part when growing The deque is split at the marker lo, or logical index 0. Move the shortest part (split by lo) when growing. This way add_front is just as fast as add_back, on average. --- src/libextra/deque.rs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index e8f8a31d7be0b..3dfc90002d3c7 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -108,7 +108,7 @@ impl Deque { /// Prepend an element to the deque pub fn add_front(&mut self, t: T) { if self.nelts == self.elts.len() { - grow(self.nelts, self.lo, &mut self.elts); + grow(self.nelts, &mut self.lo, &mut self.elts); } if self.lo == 0u { self.lo = self.elts.len() - 1u; @@ -120,7 +120,7 @@ impl Deque { /// Append an element to the deque pub fn add_back(&mut self, t: T) { if self.nelts == self.elts.len() { - grow(self.nelts, self.lo, &mut self.elts); + grow(self.nelts, &mut self.lo, &mut self.elts); } let hi = self.raw_index(self.nelts); self.elts[hi] = Some(t); @@ -230,18 +230,36 @@ iterator!{impl DequeMutRevIterator -> &'self mut T, get_mut_ref, -1} /// Grow is only called on full elts, so nelts is also len(elts), unlike /// elsewhere. -fn grow(nelts: uint, lo: uint, elts: &mut ~[Option]) { +fn grow(nelts: uint, loptr: &mut uint, elts: &mut ~[Option]) { assert_eq!(nelts, elts.len()); - let newlen = elts.capacity() * 2; + let lo = *loptr; + let newlen = nelts * 2; elts.reserve(newlen); /* fill with None */ for uint::range(elts.len(), elts.capacity()) |_| { elts.push(None); } - /* move the former wraparound to the new half */ - for uint::range(0, lo) |i| { - elts.swap(i, nelts + i); + + /* + Move the shortest half into the newly reserved area. + lo ---->| + nelts ----------->| + [o o o|o o o o o] + A [. . .|o o o o o o o o|. . . . .] + B [o o o|. . . . . . . .|o o o o o] + */ + + assert!(newlen - nelts/2 >= nelts); + if lo <= (nelts - lo) { // A + for uint::range(0, lo) |i| { + elts.swap(i, nelts + i); + } + } else { // B + for uint::range(lo, nelts) |i| { + elts.swap(i, newlen - nelts + i); + } + *loptr += newlen - nelts; } } From 0ff5c17cbbef0aedfa2eb1142cbf7a87abfd1d05 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:45 +0200 Subject: [PATCH 09/11] deque: Implement Deque::with_capacity. Lower initial capacity to 8. We need a reasonably small initial capacity to make Deques faster for the common case. --- src/libextra/deque.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index 3dfc90002d3c7..c537167946c7f 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -14,7 +14,8 @@ use std::uint; use std::vec; use std::iterator::FromIterator; -static INITIAL_CAPACITY: uint = 32u; // 2^5 +static INITIAL_CAPACITY: uint = 8u; // 2^3 +static MINIMUM_CAPACITY: uint = 2u; #[allow(missing_doc)] pub struct Deque { @@ -43,8 +44,13 @@ impl Mutable for Deque { impl Deque { /// Create an empty Deque pub fn new() -> Deque { + Deque::with_capacity(INITIAL_CAPACITY) + } + + /// Create an empty Deque with space for at least `n` elements. + pub fn with_capacity(n: uint) -> Deque { Deque{nelts: 0, lo: 0, - elts: vec::from_fn(INITIAL_CAPACITY, |_| None)} + elts: vec::from_fn(uint::max(MINIMUM_CAPACITY, n), |_| None)} } /// Return a reference to the first element in the deque @@ -527,6 +533,16 @@ mod tests { } + #[test] + fn test_with_capacity() { + let mut d = Deque::with_capacity(0); + d.add_back(1); + assert_eq!(d.len(), 1); + let mut d = Deque::with_capacity(50); + d.add_back(1); + assert_eq!(d.len(), 1); + } + #[test] fn test_reserve() { let mut d = Deque::new(); From 07e2775dff0643f0f8f66f5ecf92ab7ee163bce4 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 05:42:46 +0200 Subject: [PATCH 10/11] deque: Remove obsolete methods .each() and .eachi() --- src/libextra/deque.rs | 29 ----------------------------- src/libextra/serialize.rs | 2 +- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index c537167946c7f..9e19d8746a40c 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -77,16 +77,6 @@ impl Deque { get(self.elts, idx) } - /// Iterate over the elements in the deque - pub fn each(&self, f: &fn(&T) -> bool) -> bool { - self.eachi(|_i, e| f(e)) - } - - /// Iterate over the elements in the deque by index - pub fn eachi(&self, f: &fn(uint, &T) -> bool) -> bool { - uint::range(0, self.nelts, |i| f(i, self.get(i as int))) - } - /// Remove and return the first element in the deque /// /// Fails if the deque is empty @@ -514,25 +504,6 @@ mod tests { test_parameterized::(reccy1, reccy2, reccy3, reccy4); } - #[test] - fn test_eachi() { - let mut deq = Deque::new(); - deq.add_back(1); - deq.add_back(2); - deq.add_back(3); - - for deq.eachi |i, e| { - assert_eq!(*e, i + 1); - } - - deq.pop_front(); - - for deq.eachi |i, e| { - assert_eq!(*e, i + 2); - } - - } - #[test] fn test_with_capacity() { let mut d = Deque::with_capacity(0); diff --git a/src/libextra/serialize.rs b/src/libextra/serialize.rs index 66b178f49f7f7..b1383948bf72b 100644 --- a/src/libextra/serialize.rs +++ b/src/libextra/serialize.rs @@ -682,7 +682,7 @@ impl< > Encodable for Deque { fn encode(&self, s: &mut S) { do s.emit_seq(self.len()) |s| { - for self.eachi |i, e| { + for self.iter().enumerate().advance |(i, e)| { s.emit_seq_elt(i, |s| e.encode(s)); } } From 10c7698d4b43aa9bd9b30df5e0769189d3a83110 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 6 Jul 2013 15:27:32 +0200 Subject: [PATCH 11/11] deque: Implement Clone and Eq for Deque --- src/libextra/deque.rs | 49 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index 9e19d8746a40c..36ebf295aabaa 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -18,6 +18,7 @@ static INITIAL_CAPACITY: uint = 8u; // 2^3 static MINIMUM_CAPACITY: uint = 2u; #[allow(missing_doc)] +#[deriving(Clone)] pub struct Deque { priv nelts: uint, priv lo: uint, @@ -272,6 +273,16 @@ fn raw_index(lo: uint, len: uint, index: uint) -> uint { } } +impl Eq for Deque { + fn eq(&self, other: &Deque) -> bool { + self.nelts == other.nelts && + self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) + } + fn ne(&self, other: &Deque) -> bool { + !self.eq(other) + } +} + impl> FromIterator for Deque { fn from_iterator(iterator: &mut T) -> Deque { let mut deq = Deque::new(); @@ -631,4 +642,42 @@ mod tests { } assert_eq!(deq.len(), 256); } + + #[test] + fn test_clone() { + let mut d = Deque::new(); + d.add_front(17); + d.add_front(42); + d.add_back(137); + d.add_back(137); + assert_eq!(d.len(), 4u); + let mut e = d.clone(); + assert_eq!(e.len(), 4u); + while !d.is_empty() { + assert_eq!(d.pop_back(), e.pop_back()); + } + assert_eq!(d.len(), 0u); + assert_eq!(e.len(), 0u); + } + + #[test] + fn test_eq() { + let mut d = Deque::new(); + assert_eq!(&d, &Deque::with_capacity(0)); + d.add_front(137); + d.add_front(17); + d.add_front(42); + d.add_back(137); + let mut e = Deque::with_capacity(0); + e.add_back(42); + e.add_back(17); + e.add_back(137); + e.add_back(137); + assert_eq!(&e, &d); + e.pop_back(); + e.add_back(0); + assert!(e != d); + e.clear(); + assert_eq!(e, Deque::new()); + } }