From b8786a5cbac0c0868e28000f8936ae91fd2ef926 Mon Sep 17 00:00:00 2001 From: Guillaume Pinot Date: Tue, 14 Oct 2014 09:41:57 +0200 Subject: [PATCH 1/2] improve shootout-reverse-complement.rs using unsafe code --- src/test/bench/shootout-reverse-complement.rs | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index e3fa6334f77cc..e42723059cfac 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -98,19 +98,44 @@ fn main() { // reverse complement, as // seq.reverse(); for c in seq.iter_mut() {*c = complements[*c]} // but faster: - let mut it = seq.iter_mut(); - loop { - match (it.next(), it.next_back()) { - (Some(front), Some(back)) => { - let tmp = complements[*front as uint]; - *front = complements[*back as uint]; - *back = tmp; - } - (Some(last), None) => *last = complements[*last as uint], // last element - _ => break // vector exhausted. - } + for (front, back) in TwoSideIterator::new(seq) { + let tmp = complements[*front as uint]; + *front = complements[*back as uint]; + *back = tmp; + } + if seq.len() % 2 == 1 { + let middle = &mut seq[seq.len() / 2]; + *middle = complements[*middle as uint]; } } stdout().write(data.as_slice()).unwrap(); } + +pub struct TwoSideIterator<'a, T: 'a> { + last: uint, + nb: uint, + cur: uint, + slice: &'a mut [T] +} +impl<'a, T> TwoSideIterator<'a, T> { + pub fn new(s: &'a mut [T]) -> TwoSideIterator<'a, T> { + TwoSideIterator { + last: s.len() - 1, + nb: s.len() / 2, + cur: 0, + slice: s + } + } +} +impl<'a, T> Iterator<(&'a mut T, &'a mut T)> for TwoSideIterator<'a, T> { + fn next(&mut self) -> Option<(&'a mut T, &'a mut T)> { + if self.cur >= self.nb { return None; } + let res = unsafe { + (std::mem::transmute(self.slice.unsafe_mut(self.cur)), + std::mem::transmute(self.slice.unsafe_mut(self.last - self.cur))) + }; + self.cur += 1; + Some(res) + } +} From 1a6f1ebad541e179f7418ce0102540cb15fb455e Mon Sep 17 00:00:00 2001 From: Guillaume Pinot Date: Thu, 16 Oct 2014 00:11:06 +0200 Subject: [PATCH 2/2] shootout-reverse-complement: reimplement TwoSideIter using pointers --- src/test/bench/shootout-reverse-complement.rs | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index e42723059cfac..352d351973bc6 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -96,9 +96,9 @@ fn main() { } // reverse complement, as - // seq.reverse(); for c in seq.iter_mut() {*c = complements[*c]} + // seq.reverse(); for c in seq.iter_mut() { *c = complements[*c] } // but faster: - for (front, back) in TwoSideIterator::new(seq) { + for (front, back) in two_side_iter(seq) { let tmp = complements[*front as uint]; *front = complements[*back as uint]; *back = tmp; @@ -112,30 +112,39 @@ fn main() { stdout().write(data.as_slice()).unwrap(); } -pub struct TwoSideIterator<'a, T: 'a> { - last: uint, - nb: uint, - cur: uint, - slice: &'a mut [T] +pub struct TwoSideIter<'a, T: 'a> { + first: *mut T, + last: *mut T, + marker: std::kinds::marker::ContravariantLifetime<'a>, + marker2: std::kinds::marker::NoCopy } -impl<'a, T> TwoSideIterator<'a, T> { - pub fn new(s: &'a mut [T]) -> TwoSideIterator<'a, T> { - TwoSideIterator { - last: s.len() - 1, - nb: s.len() / 2, - cur: 0, - slice: s - } + +pub fn two_side_iter<'a, T>(slice: &'a mut [T]) -> TwoSideIter<'a, T> { + let len = slice.len(); + let first = slice.as_mut_ptr(); + let last = if len == 0 { + first + } else { + unsafe { first.offset(len as int - 1) } + }; + + TwoSideIter { + first: first, + last: last, + marker: std::kinds::marker::ContravariantLifetime, + marker2: std::kinds::marker::NoCopy } } -impl<'a, T> Iterator<(&'a mut T, &'a mut T)> for TwoSideIterator<'a, T> { + +impl<'a, T> Iterator<(&'a mut T, &'a mut T)> for TwoSideIter<'a, T> { fn next(&mut self) -> Option<(&'a mut T, &'a mut T)> { - if self.cur >= self.nb { return None; } - let res = unsafe { - (std::mem::transmute(self.slice.unsafe_mut(self.cur)), - std::mem::transmute(self.slice.unsafe_mut(self.last - self.cur))) - }; - self.cur += 1; - Some(res) + if self.first < self.last { + let result = unsafe { (&mut *self.first, &mut *self.last) }; + self.first = unsafe { self.first.offset(1) }; + self.last = unsafe { self.last.offset(-1) }; + Some(result) + } else { + None + } } }