auto merge of #18056 : TeXitoi/rust/shootout-reverse-complement-improvement, r=alexcrichton

This is some improvement as asked and discused here: http://www.reddit.com/r/rust/comments/2j2ij3/benchmark_improvement_reverse_compliment/

Before:
```
real    0m0.396s
user    0m0.280s
sys     0m0.112s
```
after:
```
real    0m0.293s
user    0m0.216s
sys     0m0.076s
```
best C version:
```
real    0m0.135s
user    0m0.132s
sys     0m0.060s
```

Another possibility will be to add a `DoubleEndedIterator::next_two_side()` with a deffault implementation, and specialising it for slices, and use it here (`MutableSlice::reverse()` can then become safe). This benchmark will then be safe.

What do you think?
This commit is contained in:
bors 2014-10-17 05:42:19 +00:00
commit 0f8df80804
1 changed files with 46 additions and 12 deletions

View File

@ -96,21 +96,55 @@ 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:
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 two_side_iter(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 TwoSideIter<'a, T: 'a> {
first: *mut T,
last: *mut T,
marker: std::kinds::marker::ContravariantLifetime<'a>,
marker2: std::kinds::marker::NoCopy
}
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 TwoSideIter<'a, T> {
fn next(&mut self) -> Option<(&'a mut T, &'a mut T)> {
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
}
}
}