//! A deque. Untested as of yet. Likely buggy #[forbid(deprecated_mode)]; #[forbid(non_camel_case_types)]; use option::{Some, None}; use dvec::DVec; use core::cmp::{Eq}; pub trait Deque { fn size() -> uint; fn add_front(v: T); fn add_back(v: T); fn pop_front() -> T; fn pop_back() -> T; fn peek_front() -> T; fn peek_back() -> T; fn get(int) -> T; } // FIXME (#2343) eventually, a proper datatype plus an exported impl would // be preferrable. pub fn create() -> Deque { type Cell = Option; let initial_capacity: uint = 32u; // 2^5 /** * Grow is only called on full elts, so nelts is also len(elts), unlike * elsewhere. */ fn grow(nelts: uint, lo: uint, elts: ~[Cell]) -> ~[Cell] { let mut elts = move elts; assert (nelts == vec::len(elts)); let mut rv = ~[]; let mut i = 0u; let nalloc = uint::next_power_of_two(nelts + 1u); while i < nalloc { if i < nelts { rv.push(elts[(lo + i) % nelts]); } else { rv.push(None); } i += 1u; } move rv } fn get(elts: &DVec>, i: uint) -> T { match (*elts).get_elt(i) { Some(move t) => t, _ => fail } } type Repr = {mut nelts: uint, mut lo: uint, mut hi: uint, elts: DVec>}; impl Repr: Deque { fn size() -> uint { return self.nelts; } fn add_front(t: T) { let oldlo: uint = self.lo; if self.lo == 0u { self.lo = self.elts.len() - 1u; } else { self.lo -= 1u; } if self.lo == self.hi { self.elts.swap(|v| grow(self.nelts, oldlo, move v)); self.lo = self.elts.len() - 1u; self.hi = self.nelts; } self.elts.set_elt(self.lo, Some(t)); self.nelts += 1u; } fn add_back(t: T) { if self.lo == self.hi && self.nelts != 0u { self.elts.swap(|v| grow(self.nelts, self.lo, move v)); self.lo = 0u; self.hi = self.nelts; } self.elts.set_elt(self.hi, Some(t)); self.hi = (self.hi + 1u) % self.elts.len(); self.nelts += 1u; } /** * We actually release (turn to none()) the T we're popping so * that we don't keep anyone's refcount up unexpectedly. */ fn pop_front() -> T { let t: T = get(&self.elts, self.lo); self.elts.set_elt(self.lo, None); self.lo = (self.lo + 1u) % self.elts.len(); self.nelts -= 1u; return t; } fn pop_back() -> T { if self.hi == 0u { self.hi = self.elts.len() - 1u; } else { self.hi -= 1u; } let t: T = get(&self.elts, self.hi); self.elts.set_elt(self.hi, None); self.nelts -= 1u; return t; } fn peek_front() -> T { return get(&self.elts, self.lo); } fn peek_back() -> T { return get(&self.elts, self.hi - 1u); } fn get(i: int) -> T { let idx = (self.lo + (i as uint)) % self.elts.len(); return get(&self.elts, idx); } } let repr: Repr = { mut nelts: 0u, mut lo: 0u, mut hi: 0u, elts: dvec::from_vec( vec::from_elem(initial_capacity, None)) }; (move repr) as Deque:: } #[cfg(test)] mod tests { #[test] fn test_simple() { let d: deque::Deque = deque::create::(); assert (d.size() == 0u); d.add_front(17); d.add_front(42); d.add_back(137); assert (d.size() == 3u); d.add_back(137); assert (d.size() == 4u); log(debug, d.peek_front()); assert (d.peek_front() == 42); log(debug, d.peek_back()); assert (d.peek_back() == 137); let mut i: int = d.pop_front(); log(debug, i); assert (i == 42); i = d.pop_back(); log(debug, i); assert (i == 137); i = d.pop_back(); log(debug, i); assert (i == 137); i = d.pop_back(); log(debug, i); assert (i == 17); assert (d.size() == 0u); d.add_back(3); assert (d.size() == 1u); d.add_front(2); assert (d.size() == 2u); d.add_back(4); assert (d.size() == 3u); d.add_front(1); assert (d.size() == 4u); log(debug, d.get(0)); log(debug, d.get(1)); log(debug, d.get(2)); log(debug, d.get(3)); assert (d.get(0) == 1); assert (d.get(1) == 2); assert (d.get(2) == 3); assert (d.get(3) == 4); } #[test] fn test_boxes() { let a: @int = @5; let b: @int = @72; let c: @int = @64; let d: @int = @175; let deq: deque::Deque<@int> = deque::create::<@int>(); assert (deq.size() == 0u); deq.add_front(a); deq.add_front(b); deq.add_back(c); assert (deq.size() == 3u); deq.add_back(d); assert (deq.size() == 4u); assert (deq.peek_front() == b); assert (deq.peek_back() == d); assert (deq.pop_front() == b); assert (deq.pop_back() == d); assert (deq.pop_back() == c); assert (deq.pop_back() == a); assert (deq.size() == 0u); deq.add_back(c); assert (deq.size() == 1u); deq.add_front(b); assert (deq.size() == 2u); deq.add_back(d); assert (deq.size() == 3u); deq.add_front(a); assert (deq.size() == 4u); assert (deq.get(0) == a); assert (deq.get(1) == b); assert (deq.get(2) == c); assert (deq.get(3) == d); } fn test_parameterized(a: T, b: T, c: T, d: T) { let deq: deque::Deque = deque::create::(); assert (deq.size() == 0u); deq.add_front(a); deq.add_front(b); deq.add_back(c); assert (deq.size() == 3u); deq.add_back(d); assert (deq.size() == 4u); assert deq.peek_front() == b; assert deq.peek_back() == d; assert deq.pop_front() == b; assert deq.pop_back() == d; assert deq.pop_back() == c; assert deq.pop_back() == a; assert (deq.size() == 0u); deq.add_back(c); assert (deq.size() == 1u); deq.add_front(b); assert (deq.size() == 2u); deq.add_back(d); assert (deq.size() == 3u); deq.add_front(a); assert (deq.size() == 4u); assert deq.get(0) == a; assert deq.get(1) == b; assert deq.get(2) == c; assert deq.get(3) == d; } enum Taggy { One(int), Two(int, int), Three(int, int, int), } enum Taggypar { Onepar(int), Twopar(int, int), Threepar(int, int, int), } type RecCy = {x: int, y: int, t: Taggy}; impl Taggy : Eq { #[cfg(stage0)] pure fn eq(other: &Taggy) -> bool { match self { One(a1) => match (*other) { One(b1) => return a1 == b1, _ => return false }, Two(a1, a2) => match (*other) { Two(b1, b2) => return a1 == b1 && a2 == b2, _ => return false }, Three(a1, a2, a3) => match (*other) { Three(b1, b2, b3) => return a1 == b1 && a2 == b2 && a3 == b3, _ => return false } } } #[cfg(stage1)] #[cfg(stage2)] pure fn eq(&self, other: &Taggy) -> bool { match (*self) { One(a1) => match (*other) { One(b1) => return a1 == b1, _ => return false }, Two(a1, a2) => match (*other) { Two(b1, b2) => return a1 == b1 && a2 == b2, _ => return false }, Three(a1, a2, a3) => match (*other) { Three(b1, b2, b3) => return a1 == b1 && a2 == b2 && a3 == b3, _ => return false } } } #[cfg(stage0)] pure fn ne(other: &Taggy) -> bool { !self.eq(other) } #[cfg(stage1)] #[cfg(stage2)] pure fn ne(&self, other: &Taggy) -> bool { !(*self).eq(other) } } impl Taggypar : Eq { //let eq4: EqFn> = |x,y| taggypareq::(x, y); #[cfg(stage0)] pure fn eq(other: &Taggypar) -> bool { match self { Onepar::(a1) => match (*other) { Onepar::(b1) => return a1 == b1, _ => return false }, Twopar::(a1, a2) => match (*other) { Twopar::(b1, b2) => return a1 == b1 && a2 == b2, _ => return false }, Threepar::(a1, a2, a3) => match (*other) { Threepar::(b1, b2, b3) => { return a1 == b1 && a2 == b2 && a3 == b3 } _ => return false } } } #[cfg(stage1)] #[cfg(stage2)] pure fn eq(&self, other: &Taggypar) -> bool { match (*self) { Onepar::(a1) => match (*other) { Onepar::(b1) => return a1 == b1, _ => return false }, Twopar::(a1, a2) => match (*other) { Twopar::(b1, b2) => return a1 == b1 && a2 == b2, _ => return false }, Threepar::(a1, a2, a3) => match (*other) { Threepar::(b1, b2, b3) => { return a1 == b1 && a2 == b2 && a3 == b3 } _ => return false } } } #[cfg(stage0)] pure fn ne(other: &Taggypar) -> bool { !self.eq(other) } #[cfg(stage1)] #[cfg(stage2)] pure fn ne(&self, other: &Taggypar) -> bool { !(*self).eq(other) } } impl RecCy : Eq { #[cfg(stage0)] pure fn eq(other: &RecCy) -> bool { return self.x == (*other).x && self.y == (*other).y && self.t == (*other).t; } #[cfg(stage1)] #[cfg(stage2)] pure fn eq(&self, other: &RecCy) -> bool { return (*self).x == (*other).x && (*self).y == (*other).y && (*self).t == (*other).t; } #[cfg(stage0)] pure fn ne(other: &RecCy) -> bool { !self.eq(other) } #[cfg(stage1)] #[cfg(stage2)] pure fn ne(&self, other: &RecCy) -> bool { !(*self).eq(other) } } #[test] fn test_param_int() { test_parameterized::(5, 72, 64, 175); } #[test] fn test_param_at_int() { test_parameterized::<@int>(@5, @72, @64, @175); } #[test] fn test_param_taggy() { test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); } #[test] fn test_param_taggypar() { test_parameterized::>(Onepar::(1), Twopar::(1, 2), Threepar::(1, 2, 3), Twopar::(17, 42)); } #[test] fn test_param_reccy() { let reccy1: RecCy = {x: 1, y: 2, t: One(1)}; let reccy2: RecCy = {x: 345, y: 2, t: Two(1, 2)}; let reccy3: RecCy = {x: 1, y: 777, t: Three(1, 2, 3)}; let reccy4: RecCy = {x: 19, y: 252, t: Two(17, 42)}; test_parameterized::(reccy1, reccy2, reccy3, reccy4); } }