diff options
| author | bors <bors@rust-lang.org> | 2014-10-17 05:42:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-10-17 05:42:19 +0000 |
| commit | 0f8df80804b2c7e89acc3c8e046a1ac7a90124f6 (patch) | |
| tree | 896a86f527b517ae7341ac0a14a6152394e261c9 /src/test | |
| parent | 3dec727297e6ebd6614219a93f376d8181ab11b1 (diff) | |
| parent | 1a6f1ebad541e179f7418ce0102540cb15fb455e (diff) | |
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?
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/bench/shootout-reverse-complement.rs | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index e3fa6334f77..352d351973b 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -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 + } + } +} |
