diff options
| author | blake2-ppc <blake2-ppc> | 2013-07-06 05:42:45 +0200 |
|---|---|---|
| committer | blake2-ppc <blake2-ppc> | 2013-07-06 07:26:04 +0200 |
| commit | 8a3267672c43e7cc116e588dd21998d14fc21ba4 (patch) | |
| tree | e2847b0d0a7a3d69f1ebb0323058c521931dba44 | |
| parent | 75015c36f9fa6d0958874c1a448d6d67056145ae (diff) | |
| download | rust-8a3267672c43e7cc116e588dd21998d14fc21ba4.tar.gz rust-8a3267672c43e7cc116e588dd21998d14fc21ba4.zip | |
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.
| -rw-r--r-- | src/libextra/deque.rs | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index e8f8a31d7be..3dfc90002d3 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -108,7 +108,7 @@ impl<T> Deque<T> { /// 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<T> Deque<T> { /// 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<T>(nelts: uint, lo: uint, elts: &mut ~[Option<T>]) { +fn grow<T>(nelts: uint, loptr: &mut uint, elts: &mut ~[Option<T>]) { 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; } } |
